12cab237bSDimitry Andric //===-- RandomIRBuilder.cpp -----------------------------------------------===//
22cab237bSDimitry Andric //
32cab237bSDimitry Andric //                     The LLVM Compiler Infrastructure
42cab237bSDimitry Andric //
52cab237bSDimitry Andric // This file is distributed under the University of Illinois Open Source
62cab237bSDimitry Andric // License. See LICENSE.TXT for details.
72cab237bSDimitry Andric //
82cab237bSDimitry Andric //===----------------------------------------------------------------------===//
92cab237bSDimitry Andric 
102cab237bSDimitry Andric #include "llvm/FuzzMutate/RandomIRBuilder.h"
112cab237bSDimitry Andric #include "llvm/ADT/STLExtras.h"
122cab237bSDimitry Andric #include "llvm/FuzzMutate/Random.h"
132cab237bSDimitry Andric #include "llvm/IR/BasicBlock.h"
142cab237bSDimitry Andric #include "llvm/IR/Constants.h"
152cab237bSDimitry Andric #include "llvm/IR/Function.h"
162cab237bSDimitry Andric #include "llvm/IR/Instructions.h"
172cab237bSDimitry Andric #include "llvm/IR/IntrinsicInst.h"
182cab237bSDimitry Andric 
192cab237bSDimitry Andric using namespace llvm;
202cab237bSDimitry Andric using namespace fuzzerop;
212cab237bSDimitry Andric 
findOrCreateSource(BasicBlock & BB,ArrayRef<Instruction * > Insts)222cab237bSDimitry Andric Value *RandomIRBuilder::findOrCreateSource(BasicBlock &BB,
232cab237bSDimitry Andric                                            ArrayRef<Instruction *> Insts) {
242cab237bSDimitry Andric   return findOrCreateSource(BB, Insts, {}, anyType());
252cab237bSDimitry Andric }
262cab237bSDimitry Andric 
findOrCreateSource(BasicBlock & BB,ArrayRef<Instruction * > Insts,ArrayRef<Value * > Srcs,SourcePred Pred)272cab237bSDimitry Andric Value *RandomIRBuilder::findOrCreateSource(BasicBlock &BB,
282cab237bSDimitry Andric                                            ArrayRef<Instruction *> Insts,
292cab237bSDimitry Andric                                            ArrayRef<Value *> Srcs,
302cab237bSDimitry Andric                                            SourcePred Pred) {
312cab237bSDimitry Andric   auto MatchesPred = [&Srcs, &Pred](Instruction *Inst) {
322cab237bSDimitry Andric     return Pred.matches(Srcs, Inst);
332cab237bSDimitry Andric   };
342cab237bSDimitry Andric   auto RS = makeSampler(Rand, make_filter_range(Insts, MatchesPred));
352cab237bSDimitry Andric   // Also consider choosing no source, meaning we want a new one.
362cab237bSDimitry Andric   RS.sample(nullptr, /*Weight=*/1);
372cab237bSDimitry Andric   if (Instruction *Src = RS.getSelection())
382cab237bSDimitry Andric     return Src;
392cab237bSDimitry Andric   return newSource(BB, Insts, Srcs, Pred);
402cab237bSDimitry Andric }
412cab237bSDimitry Andric 
newSource(BasicBlock & BB,ArrayRef<Instruction * > Insts,ArrayRef<Value * > Srcs,SourcePred Pred)422cab237bSDimitry Andric Value *RandomIRBuilder::newSource(BasicBlock &BB, ArrayRef<Instruction *> Insts,
432cab237bSDimitry Andric                                   ArrayRef<Value *> Srcs, SourcePred Pred) {
442cab237bSDimitry Andric   // Generate some constants to choose from.
452cab237bSDimitry Andric   auto RS = makeSampler<Value *>(Rand);
462cab237bSDimitry Andric   RS.sample(Pred.generate(Srcs, KnownTypes));
472cab237bSDimitry Andric 
482cab237bSDimitry Andric   // If we can find a pointer to load from, use it half the time.
492cab237bSDimitry Andric   Value *Ptr = findPointer(BB, Insts, Srcs, Pred);
502cab237bSDimitry Andric   if (Ptr) {
512cab237bSDimitry Andric     // Create load from the chosen pointer
522cab237bSDimitry Andric     auto IP = BB.getFirstInsertionPt();
532cab237bSDimitry Andric     if (auto *I = dyn_cast<Instruction>(Ptr)) {
542cab237bSDimitry Andric       IP = ++I->getIterator();
552cab237bSDimitry Andric       assert(IP != BB.end() && "guaranteed by the findPointer");
562cab237bSDimitry Andric     }
572cab237bSDimitry Andric     auto *NewLoad = new LoadInst(Ptr, "L", &*IP);
582cab237bSDimitry Andric 
592cab237bSDimitry Andric     // Only sample this load if it really matches the descriptor
602cab237bSDimitry Andric     if (Pred.matches(Srcs, NewLoad))
612cab237bSDimitry Andric       RS.sample(NewLoad, RS.totalWeight());
622cab237bSDimitry Andric     else
632cab237bSDimitry Andric       NewLoad->eraseFromParent();
642cab237bSDimitry Andric   }
652cab237bSDimitry Andric 
662cab237bSDimitry Andric   assert(!RS.isEmpty() && "Failed to generate sources");
672cab237bSDimitry Andric   return RS.getSelection();
682cab237bSDimitry Andric }
692cab237bSDimitry Andric 
isCompatibleReplacement(const Instruction * I,const Use & Operand,const Value * Replacement)702cab237bSDimitry Andric static bool isCompatibleReplacement(const Instruction *I, const Use &Operand,
712cab237bSDimitry Andric                                     const Value *Replacement) {
722cab237bSDimitry Andric   if (Operand->getType() != Replacement->getType())
732cab237bSDimitry Andric     return false;
742cab237bSDimitry Andric   switch (I->getOpcode()) {
752cab237bSDimitry Andric   case Instruction::GetElementPtr:
762cab237bSDimitry Andric   case Instruction::ExtractElement:
772cab237bSDimitry Andric   case Instruction::ExtractValue:
782cab237bSDimitry Andric     // TODO: We could potentially validate these, but for now just leave indices
792cab237bSDimitry Andric     // alone.
802cab237bSDimitry Andric     if (Operand.getOperandNo() >= 1)
812cab237bSDimitry Andric       return false;
822cab237bSDimitry Andric     break;
832cab237bSDimitry Andric   case Instruction::InsertValue:
842cab237bSDimitry Andric   case Instruction::InsertElement:
852cab237bSDimitry Andric   case Instruction::ShuffleVector:
862cab237bSDimitry Andric     if (Operand.getOperandNo() >= 2)
872cab237bSDimitry Andric       return false;
882cab237bSDimitry Andric     break;
892cab237bSDimitry Andric   default:
902cab237bSDimitry Andric     break;
912cab237bSDimitry Andric   }
922cab237bSDimitry Andric   return true;
932cab237bSDimitry Andric }
942cab237bSDimitry Andric 
connectToSink(BasicBlock & BB,ArrayRef<Instruction * > Insts,Value * V)952cab237bSDimitry Andric void RandomIRBuilder::connectToSink(BasicBlock &BB,
962cab237bSDimitry Andric                                     ArrayRef<Instruction *> Insts, Value *V) {
972cab237bSDimitry Andric   auto RS = makeSampler<Use *>(Rand);
982cab237bSDimitry Andric   for (auto &I : Insts) {
992cab237bSDimitry Andric     if (isa<IntrinsicInst>(I))
1002cab237bSDimitry Andric       // TODO: Replacing operands of intrinsics would be interesting, but
1012cab237bSDimitry Andric       // there's no easy way to verify that a given replacement is valid given
1022cab237bSDimitry Andric       // that intrinsics can impose arbitrary constraints.
1032cab237bSDimitry Andric       continue;
1042cab237bSDimitry Andric     for (Use &U : I->operands())
1052cab237bSDimitry Andric       if (isCompatibleReplacement(I, U, V))
1062cab237bSDimitry Andric         RS.sample(&U, 1);
1072cab237bSDimitry Andric   }
1082cab237bSDimitry Andric   // Also consider choosing no sink, meaning we want a new one.
1092cab237bSDimitry Andric   RS.sample(nullptr, /*Weight=*/1);
1102cab237bSDimitry Andric 
1112cab237bSDimitry Andric   if (Use *Sink = RS.getSelection()) {
1122cab237bSDimitry Andric     User *U = Sink->getUser();
1132cab237bSDimitry Andric     unsigned OpNo = Sink->getOperandNo();
1142cab237bSDimitry Andric     U->setOperand(OpNo, V);
1152cab237bSDimitry Andric     return;
1162cab237bSDimitry Andric   }
1172cab237bSDimitry Andric   newSink(BB, Insts, V);
1182cab237bSDimitry Andric }
1192cab237bSDimitry Andric 
newSink(BasicBlock & BB,ArrayRef<Instruction * > Insts,Value * V)1202cab237bSDimitry Andric void RandomIRBuilder::newSink(BasicBlock &BB, ArrayRef<Instruction *> Insts,
1212cab237bSDimitry Andric                               Value *V) {
1222cab237bSDimitry Andric   Value *Ptr = findPointer(BB, Insts, {V}, matchFirstType());
1232cab237bSDimitry Andric   if (!Ptr) {
1242cab237bSDimitry Andric     if (uniform(Rand, 0, 1))
1252cab237bSDimitry Andric       Ptr = new AllocaInst(V->getType(), 0, "A", &*BB.getFirstInsertionPt());
1262cab237bSDimitry Andric     else
1272cab237bSDimitry Andric       Ptr = UndefValue::get(PointerType::get(V->getType(), 0));
1282cab237bSDimitry Andric   }
1292cab237bSDimitry Andric 
1302cab237bSDimitry Andric   new StoreInst(V, Ptr, Insts.back());
1312cab237bSDimitry Andric }
1322cab237bSDimitry Andric 
findPointer(BasicBlock & BB,ArrayRef<Instruction * > Insts,ArrayRef<Value * > Srcs,SourcePred Pred)1332cab237bSDimitry Andric Value *RandomIRBuilder::findPointer(BasicBlock &BB,
1342cab237bSDimitry Andric                                     ArrayRef<Instruction *> Insts,
1352cab237bSDimitry Andric                                     ArrayRef<Value *> Srcs, SourcePred Pred) {
1362cab237bSDimitry Andric   auto IsMatchingPtr = [&Srcs, &Pred](Instruction *Inst) {
1372cab237bSDimitry Andric     // Invoke instructions sometimes produce valid pointers but currently
1382cab237bSDimitry Andric     // we can't insert loads or stores from them
139*b5893f02SDimitry Andric     if (Inst->isTerminator())
1402cab237bSDimitry Andric       return false;
1412cab237bSDimitry Andric 
1422cab237bSDimitry Andric     if (auto PtrTy = dyn_cast<PointerType>(Inst->getType())) {
1432cab237bSDimitry Andric       // We can never generate loads from non first class or non sized types
1442cab237bSDimitry Andric       if (!PtrTy->getElementType()->isSized() ||
1452cab237bSDimitry Andric           !PtrTy->getElementType()->isFirstClassType())
1462cab237bSDimitry Andric         return false;
1472cab237bSDimitry Andric 
1482cab237bSDimitry Andric       // TODO: Check if this is horribly expensive.
1492cab237bSDimitry Andric       return Pred.matches(Srcs, UndefValue::get(PtrTy->getElementType()));
1502cab237bSDimitry Andric     }
1512cab237bSDimitry Andric     return false;
1522cab237bSDimitry Andric   };
1532cab237bSDimitry Andric   if (auto RS = makeSampler(Rand, make_filter_range(Insts, IsMatchingPtr)))
1542cab237bSDimitry Andric     return RS.getSelection();
1552cab237bSDimitry Andric   return nullptr;
1562cab237bSDimitry Andric }
157