RandomIRBuilder.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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/Random.h"
  11. #include "llvm/IR/BasicBlock.h"
  12. #include "llvm/IR/Constants.h"
  13. #include "llvm/IR/Function.h"
  14. #include "llvm/IR/Instructions.h"
  15. #include "llvm/IR/IntrinsicInst.h"
  16. using namespace llvm;
  17. using namespace fuzzerop;
  18. Value *RandomIRBuilder::findOrCreateSource(BasicBlock &BB,
  19. ArrayRef<Instruction *> Insts) {
  20. return findOrCreateSource(BB, Insts, {}, anyType());
  21. }
  22. Value *RandomIRBuilder::findOrCreateSource(BasicBlock &BB,
  23. ArrayRef<Instruction *> Insts,
  24. ArrayRef<Value *> Srcs,
  25. SourcePred Pred) {
  26. auto MatchesPred = [&Srcs, &Pred](Instruction *Inst) {
  27. return Pred.matches(Srcs, Inst);
  28. };
  29. auto RS = makeSampler(Rand, make_filter_range(Insts, MatchesPred));
  30. // Also consider choosing no source, meaning we want a new one.
  31. RS.sample(nullptr, /*Weight=*/1);
  32. if (Instruction *Src = RS.getSelection())
  33. return Src;
  34. return newSource(BB, Insts, Srcs, Pred);
  35. }
  36. Value *RandomIRBuilder::newSource(BasicBlock &BB, ArrayRef<Instruction *> Insts,
  37. ArrayRef<Value *> Srcs, SourcePred Pred) {
  38. // Generate some constants to choose from.
  39. auto RS = makeSampler<Value *>(Rand);
  40. RS.sample(Pred.generate(Srcs, KnownTypes));
  41. // If we can find a pointer to load from, use it half the time.
  42. Value *Ptr = findPointer(BB, Insts, Srcs, Pred);
  43. if (Ptr) {
  44. // Create load from the chosen pointer
  45. auto IP = BB.getFirstInsertionPt();
  46. if (auto *I = dyn_cast<Instruction>(Ptr)) {
  47. IP = ++I->getIterator();
  48. assert(IP != BB.end() && "guaranteed by the findPointer");
  49. }
  50. auto *NewLoad =
  51. new LoadInst(Ptr->getType()->getPointerElementType(), Ptr, "L", &*IP);
  52. // Only sample this load if it really matches the descriptor
  53. if (Pred.matches(Srcs, NewLoad))
  54. RS.sample(NewLoad, RS.totalWeight());
  55. else
  56. NewLoad->eraseFromParent();
  57. }
  58. assert(!RS.isEmpty() && "Failed to generate sources");
  59. return RS.getSelection();
  60. }
  61. static bool isCompatibleReplacement(const Instruction *I, const Use &Operand,
  62. const Value *Replacement) {
  63. if (Operand->getType() != Replacement->getType())
  64. return false;
  65. switch (I->getOpcode()) {
  66. case Instruction::GetElementPtr:
  67. case Instruction::ExtractElement:
  68. case Instruction::ExtractValue:
  69. // TODO: We could potentially validate these, but for now just leave indices
  70. // alone.
  71. if (Operand.getOperandNo() >= 1)
  72. return false;
  73. break;
  74. case Instruction::InsertValue:
  75. case Instruction::InsertElement:
  76. case Instruction::ShuffleVector:
  77. if (Operand.getOperandNo() >= 2)
  78. return false;
  79. break;
  80. default:
  81. break;
  82. }
  83. return true;
  84. }
  85. void RandomIRBuilder::connectToSink(BasicBlock &BB,
  86. ArrayRef<Instruction *> Insts, Value *V) {
  87. auto RS = makeSampler<Use *>(Rand);
  88. for (auto &I : Insts) {
  89. if (isa<IntrinsicInst>(I))
  90. // TODO: Replacing operands of intrinsics would be interesting, but
  91. // there's no easy way to verify that a given replacement is valid given
  92. // that intrinsics can impose arbitrary constraints.
  93. continue;
  94. for (Use &U : I->operands())
  95. if (isCompatibleReplacement(I, U, V))
  96. RS.sample(&U, 1);
  97. }
  98. // Also consider choosing no sink, meaning we want a new one.
  99. RS.sample(nullptr, /*Weight=*/1);
  100. if (Use *Sink = RS.getSelection()) {
  101. User *U = Sink->getUser();
  102. unsigned OpNo = Sink->getOperandNo();
  103. U->setOperand(OpNo, V);
  104. return;
  105. }
  106. newSink(BB, Insts, V);
  107. }
  108. void RandomIRBuilder::newSink(BasicBlock &BB, ArrayRef<Instruction *> Insts,
  109. Value *V) {
  110. Value *Ptr = findPointer(BB, Insts, {V}, matchFirstType());
  111. if (!Ptr) {
  112. if (uniform(Rand, 0, 1))
  113. Ptr = new AllocaInst(V->getType(), 0, "A", &*BB.getFirstInsertionPt());
  114. else
  115. Ptr = UndefValue::get(PointerType::get(V->getType(), 0));
  116. }
  117. new StoreInst(V, Ptr, Insts.back());
  118. }
  119. Value *RandomIRBuilder::findPointer(BasicBlock &BB,
  120. ArrayRef<Instruction *> Insts,
  121. ArrayRef<Value *> Srcs, SourcePred Pred) {
  122. auto IsMatchingPtr = [&Srcs, &Pred](Instruction *Inst) {
  123. // Invoke instructions sometimes produce valid pointers but currently
  124. // we can't insert loads or stores from them
  125. if (Inst->isTerminator())
  126. return false;
  127. if (auto PtrTy = dyn_cast<PointerType>(Inst->getType())) {
  128. // We can never generate loads from non first class or non sized types
  129. Type *ElemTy = PtrTy->getPointerElementType();
  130. if (!ElemTy->isSized() || !ElemTy->isFirstClassType())
  131. return false;
  132. // TODO: Check if this is horribly expensive.
  133. return Pred.matches(Srcs, UndefValue::get(ElemTy));
  134. }
  135. return false;
  136. };
  137. if (auto RS = makeSampler(Rand, make_filter_range(Insts, IsMatchingPtr)))
  138. return RS.getSelection();
  139. return nullptr;
  140. }