31
31
32
32
using namespace llvm ;
33
33
34
- static void createEmptyFunction (Module &M) {
35
- // TODO: Some arguments and a return value would probably be more interesting.
36
- LLVMContext &Context = M.getContext ();
37
- Function *F = Function::Create (FunctionType::get (Type::getVoidTy (Context), {},
38
- /* isVarArg=*/ false ),
39
- GlobalValue::ExternalLinkage, " f" , &M);
40
- BasicBlock *BB = BasicBlock::Create (Context, " BB" , F);
41
- ReturnInst::Create (Context, BB);
42
- }
43
-
44
34
void IRMutationStrategy::mutate (Module &M, RandomIRBuilder &IB) {
45
35
auto RS = makeSampler<Function *>(IB.Rand );
46
36
for (Function &F : M)
47
37
if (!F.isDeclaration ())
48
38
RS.sample (&F, /* Weight=*/ 1 );
49
39
50
- if (RS.isEmpty ())
51
- createEmptyFunction (M);
52
- else
53
- mutate (*RS.getSelection (), IB);
40
+ while (RS.totalWeight () < IB.MinFunctionNum ) {
41
+ Function *F = IB.createFunctionDefinition (M);
42
+ RS.sample (F, /* Weight=*/ 1 );
43
+ }
44
+ mutate (*RS.getSelection (), IB);
54
45
}
55
46
56
47
void IRMutationStrategy::mutate (Function &F, RandomIRBuilder &IB) {
@@ -349,10 +340,65 @@ static uint64_t getUniqueCaseValue(SmallSet<uint64_t, 4> &CasesTaken,
349
340
return tmp;
350
341
}
351
342
343
+ void InsertFunctionStrategy::mutate (BasicBlock &BB, RandomIRBuilder &IB) {
344
+ Module *M = BB.getParent ()->getParent ();
345
+ // If nullptr is selected, we will create a new function declaration.
346
+ SmallVector<Function *, 32 > Functions ({nullptr });
347
+ for (Function &F : M->functions ()) {
348
+ Functions.push_back (&F);
349
+ }
350
+
351
+ auto RS = makeSampler (IB.Rand , Functions);
352
+ Function *F = RS.getSelection ();
353
+ if (!F) {
354
+ F = IB.createFunctionDeclaration (*M);
355
+ }
356
+
357
+ FunctionType *FTy = F->getFunctionType ();
358
+ SmallVector<fuzzerop::SourcePred, 2 > SourcePreds;
359
+ if (!F->arg_empty ()) {
360
+ for (Type *ArgTy : FTy->params ()) {
361
+ SourcePreds.push_back (fuzzerop::onlyType (ArgTy));
362
+ }
363
+ }
364
+ bool isRetVoid = (F->getReturnType () == Type::getVoidTy (M->getContext ()));
365
+ auto BuilderFunc = [FTy, F, isRetVoid](ArrayRef<Value *> Srcs,
366
+ Instruction *Inst) {
367
+ StringRef Name = isRetVoid ? nullptr : " C" ;
368
+ CallInst *Call = CallInst::Create (FTy, F, Srcs, Name, Inst);
369
+ // Don't return this call inst if it return void as it can't be sinked.
370
+ return isRetVoid ? nullptr : Call;
371
+ };
372
+
373
+ SmallVector<Instruction *, 32 > Insts;
374
+ for (Instruction &I : make_range (BB.getFirstInsertionPt (), BB.end ()))
375
+ Insts.push_back (&I);
376
+ if (Insts.size () < 1 )
377
+ return ;
378
+
379
+ // Choose an insertion point for our new call instruction.
380
+ uint64_t IP = uniform<uint64_t >(IB.Rand , 0 , Insts.size () - 1 );
381
+
382
+ auto InstsBefore = ArrayRef (Insts).slice (0 , IP);
383
+ auto InstsAfter = ArrayRef (Insts).slice (IP);
384
+
385
+ // Choose a source, which will be used to constrain the operation selection.
386
+ SmallVector<Value *, 2 > Srcs;
387
+
388
+ for (const auto &Pred : ArrayRef (SourcePreds)) {
389
+ Srcs.push_back (IB.findOrCreateSource (BB, InstsBefore, Srcs, Pred));
390
+ }
391
+
392
+ if (Value *Op = BuilderFunc (Srcs, Insts[IP])) {
393
+ // Find a sink and wire up the results of the operation.
394
+ IB.connectToSink (BB, InstsAfter, Op);
395
+ }
396
+ }
397
+
352
398
void InsertCFGStrategy::mutate (BasicBlock &BB, RandomIRBuilder &IB) {
353
399
SmallVector<Instruction *, 32 > Insts;
354
- for (auto I = BB.getFirstInsertionPt (), E = BB.end (); I != E; ++I )
355
- Insts.push_back (&* I);
400
+ for (Instruction &I : make_range ( BB.getFirstInsertionPt (), BB.end ()) )
401
+ Insts.push_back (&I);
356
402
if (Insts.size () < 1 )
357
403
return ;
358
404
@@ -491,8 +537,8 @@ void InsertPHIStrategy::mutate(BasicBlock &BB, RandomIRBuilder &IB) {
491
537
PHI->addIncoming (Src, Pred);
492
538
}
493
539
SmallVector<Instruction *, 32 > InstsAfter;
494
- for (auto I = BB.getFirstInsertionPt (), E = BB.end (); I != E; ++I )
495
- InstsAfter.push_back (&* I);
540
+ for (Instruction &I : make_range ( BB.getFirstInsertionPt (), BB.end ()) )
541
+ InstsAfter.push_back (&I);
496
542
IB.connectToSink (BB, InstsAfter, PHI);
497
543
}
498
544
@@ -503,8 +549,8 @@ void SinkInstructionStrategy::mutate(Function &F, RandomIRBuilder &IB) {
503
549
}
504
550
void SinkInstructionStrategy::mutate (BasicBlock &BB, RandomIRBuilder &IB) {
505
551
SmallVector<Instruction *, 32 > Insts;
506
- for (auto I = BB.getFirstInsertionPt (), E = BB.end (); I != E; ++I )
507
- Insts.push_back (&* I);
552
+ for (Instruction &I : make_range ( BB.getFirstInsertionPt (), BB.end ()) )
553
+ Insts.push_back (&I);
508
554
if (Insts.size () < 1 )
509
555
return ;
510
556
// Choose an Instruction to mutate.
0 commit comments