LCOV - code coverage report
Current view: top level - lib/FuzzMutate - RandomIRBuilder.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 52 55 94.5 %
Date: 2018-10-20 13:21:21 Functions: 7 7 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13