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

Generated by: LCOV version 1.13