1 //===- OperationsTest.cpp - Tests for fuzzer operations -------------------===//
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/Operations.h"
11 #include "llvm/FuzzMutate/OpDescriptor.h"
12 #include "llvm/IR/Constants.h"
13 #include "llvm/IR/Instructions.h"
14 #include "llvm/IR/Module.h"
15 #include "llvm/IR/Verifier.h"
16 #include "gmock/gmock.h"
17 #include "gtest/gtest.h"
18 #include <iostream>
19 
20 // Define some pretty printers to help with debugging failures.
21 namespace llvm {
22 void PrintTo(Type *T, ::std::ostream *OS) {
23   raw_os_ostream ROS(*OS);
24   T->print(ROS);
25 }
26 
27 void PrintTo(BasicBlock *BB, ::std::ostream *OS) {
28   raw_os_ostream ROS(*OS);
29   ROS << BB << " (" << BB->getName() << ")";
30 }
31 
32 void PrintTo(Value *V, ::std::ostream *OS) {
33   raw_os_ostream ROS(*OS);
34   ROS << V << " (";
35   V->print(ROS);
36   ROS << ")";
37 }
38 void PrintTo(Constant *C, ::std::ostream *OS) { PrintTo(cast<Value>(C), OS); }
39 
40 } // namespace llvm
41 
42 using namespace llvm;
43 
44 using testing::AllOf;
45 using testing::AnyOf;
46 using testing::ElementsAre;
47 using testing::Eq;
48 using testing::Ge;
49 using testing::Each;
50 using testing::Truly;
51 using testing::NotNull;
52 using testing::PrintToString;
53 using testing::SizeIs;
54 
55 MATCHER_P(TypesMatch, V, "has type " + PrintToString(V->getType())) {
56   return arg->getType() == V->getType();
57 }
58 MATCHER_P(HasType, T, "") { return arg->getType() == T; }
59 
60 TEST(OperationsTest, SourcePreds) {
61   using namespace llvm::fuzzerop;
62 
63   LLVMContext Ctx;
64 
65   Constant *i1 = ConstantInt::getFalse(Ctx);
66   Constant *i8 = ConstantInt::get(Type::getInt8Ty(Ctx), 3);
67   Constant *i16 = ConstantInt::get(Type::getInt16Ty(Ctx), 1 << 15);
68   Constant *i32 = ConstantInt::get(Type::getInt32Ty(Ctx), 0);
69   Constant *i64 = ConstantInt::get(Type::getInt64Ty(Ctx),
70                                    std::numeric_limits<uint64_t>::max());
71   Constant *f16 = ConstantFP::getInfinity(Type::getHalfTy(Ctx));
72   Constant *f32 = ConstantFP::get(Type::getFloatTy(Ctx), 0.0);
73   Constant *f64 = ConstantFP::get(Type::getDoubleTy(Ctx), 123.45);
74   Constant *s =
75       ConstantStruct::get(StructType::create(Ctx, "OpaqueStruct"));
76   Constant *a =
77       ConstantArray::get(ArrayType::get(i32->getType(), 2), {i32, i32});
78   Constant *v8i8 = ConstantVector::getSplat(8, i8);
79   Constant *v4f16 = ConstantVector::getSplat(4, f16);
80   Constant *p0i32 =
81       ConstantPointerNull::get(PointerType::get(i32->getType(), 0));
82 
83   auto OnlyI32 = onlyType(i32->getType());
84   EXPECT_TRUE(OnlyI32.matches({}, i32));
85   EXPECT_FALSE(OnlyI32.matches({}, i64));
86   EXPECT_FALSE(OnlyI32.matches({}, p0i32));
87   EXPECT_FALSE(OnlyI32.matches({}, a));
88 
89   EXPECT_THAT(OnlyI32.generate({}, {}),
90               AllOf(SizeIs(Ge(1u)), Each(TypesMatch(i32))));
91 
92   auto AnyType = anyType();
93   EXPECT_TRUE(AnyType.matches({}, i1));
94   EXPECT_TRUE(AnyType.matches({}, f64));
95   EXPECT_TRUE(AnyType.matches({}, s));
96   EXPECT_TRUE(AnyType.matches({}, v8i8));
97   EXPECT_TRUE(AnyType.matches({}, p0i32));
98 
99   EXPECT_THAT(
100       AnyType.generate({}, {i32->getType(), f16->getType(), v8i8->getType()}),
101       Each(AnyOf(TypesMatch(i32), TypesMatch(f16), TypesMatch(v8i8))));
102 
103   auto AnyInt = anyIntType();
104   EXPECT_TRUE(AnyInt.matches({}, i1));
105   EXPECT_TRUE(AnyInt.matches({}, i64));
106   EXPECT_FALSE(AnyInt.matches({}, f32));
107   EXPECT_FALSE(AnyInt.matches({}, v4f16));
108 
109   EXPECT_THAT(
110       AnyInt.generate({}, {i32->getType(), f16->getType(), v8i8->getType()}),
111       AllOf(SizeIs(Ge(1u)), Each(TypesMatch(i32))));
112 
113   auto AnyFP = anyFloatType();
114   EXPECT_TRUE(AnyFP.matches({}, f16));
115   EXPECT_TRUE(AnyFP.matches({}, f32));
116   EXPECT_FALSE(AnyFP.matches({}, i16));
117   EXPECT_FALSE(AnyFP.matches({}, p0i32));
118   EXPECT_FALSE(AnyFP.matches({}, v4f16));
119 
120   EXPECT_THAT(
121       AnyFP.generate({}, {i32->getType(), f16->getType(), v8i8->getType()}),
122       AllOf(SizeIs(Ge(1u)), Each(TypesMatch(f16))));
123 
124   auto AnyPtr = anyPtrType();
125   EXPECT_TRUE(AnyPtr.matches({}, p0i32));
126   EXPECT_FALSE(AnyPtr.matches({}, i8));
127   EXPECT_FALSE(AnyPtr.matches({}, a));
128   EXPECT_FALSE(AnyPtr.matches({}, v8i8));
129 
130   auto isPointer = [](Value *V) { return V->getType()->isPointerTy(); };
131   EXPECT_THAT(
132       AnyPtr.generate({}, {i32->getType(), f16->getType(), v8i8->getType()}),
133       AllOf(SizeIs(Ge(3u)), Each(Truly(isPointer))));
134 
135   auto AnyVec = anyVectorType();
136   EXPECT_TRUE(AnyVec.matches({}, v8i8));
137   EXPECT_TRUE(AnyVec.matches({}, v4f16));
138   EXPECT_FALSE(AnyVec.matches({}, i8));
139   EXPECT_FALSE(AnyVec.matches({}, a));
140   EXPECT_FALSE(AnyVec.matches({}, s));
141 
142   EXPECT_THAT(AnyVec.generate({}, {v8i8->getType()}),
143               ElementsAre(TypesMatch(v8i8)));
144 
145   auto First = matchFirstType();
146   EXPECT_TRUE(First.matches({i8}, i8));
147   EXPECT_TRUE(First.matches({s, a}, s));
148   EXPECT_FALSE(First.matches({f16}, f32));
149   EXPECT_FALSE(First.matches({v4f16, f64}, f64));
150 
151   EXPECT_THAT(First.generate({i8}, {}), Each(TypesMatch(i8)));
152   EXPECT_THAT(First.generate({f16}, {i8->getType()}),
153               Each(TypesMatch(f16)));
154   EXPECT_THAT(First.generate({v8i8, i32}, {}), Each(TypesMatch(v8i8)));
155 }
156 
157 TEST(OperationsTest, SplitBlock) {
158   LLVMContext Ctx;
159 
160   Module M("M", Ctx);
161   Function *F = Function::Create(FunctionType::get(Type::getVoidTy(Ctx), {},
162                                                    /*isVarArg=*/false),
163                                  GlobalValue::ExternalLinkage, "f", &M);
164   auto SBOp = fuzzerop::splitBlockDescriptor(1);
165 
166   // Create a block with only a return and split it on the return.
167   auto *BB = BasicBlock::Create(Ctx, "BB", F);
168   auto *RI = ReturnInst::Create(Ctx, BB);
169   SBOp.BuilderFunc({UndefValue::get(Type::getInt1Ty(Ctx))}, RI);
170 
171   // We should end up with an unconditional branch from BB to BB1, and the
172   // return ends up in BB1.
173   auto *UncondBr = cast<BranchInst>(BB->getTerminator());
174   ASSERT_TRUE(UncondBr->isUnconditional());
175   auto *BB1 = UncondBr->getSuccessor(0);
176   ASSERT_THAT(RI->getParent(), Eq(BB1));
177 
178   // Now add an instruction to BB1 and split on that.
179   auto *AI = new AllocaInst(Type::getInt8Ty(Ctx), 0, "a", RI);
180   Value *Cond = ConstantInt::getFalse(Ctx);
181   SBOp.BuilderFunc({Cond}, AI);
182 
183   // We should end up with a loop back on BB1 and the instruction we split on
184   // moves to BB2.
185   auto *CondBr = cast<BranchInst>(BB1->getTerminator());
186   EXPECT_THAT(CondBr->getCondition(), Eq(Cond));
187   ASSERT_THAT(CondBr->getNumSuccessors(), Eq(2u));
188   ASSERT_THAT(CondBr->getSuccessor(0), Eq(BB1));
189   auto *BB2 = CondBr->getSuccessor(1);
190   EXPECT_THAT(AI->getParent(), Eq(BB2));
191   EXPECT_THAT(RI->getParent(), Eq(BB2));
192 
193   EXPECT_FALSE(verifyModule(M, &errs()));
194 }
195 
196 TEST(OperationsTest, SplitBlockWithPhis) {
197   LLVMContext Ctx;
198 
199   Type *Int8Ty = Type::getInt8Ty(Ctx);
200 
201   Module M("M", Ctx);
202   Function *F = Function::Create(FunctionType::get(Type::getVoidTy(Ctx), {},
203                                                    /*isVarArg=*/false),
204                                  GlobalValue::ExternalLinkage, "f", &M);
205   auto SBOp = fuzzerop::splitBlockDescriptor(1);
206 
207   // Create 3 blocks with an if-then branch.
208   auto *BB1 = BasicBlock::Create(Ctx, "BB1", F);
209   auto *BB2 = BasicBlock::Create(Ctx, "BB2", F);
210   auto *BB3 = BasicBlock::Create(Ctx, "BB3", F);
211   BranchInst::Create(BB2, BB3, ConstantInt::getFalse(Ctx), BB1);
212   BranchInst::Create(BB3, BB2);
213 
214   // Set up phi nodes selecting values for the incoming edges.
215   auto *PHI1 = PHINode::Create(Int8Ty, /*NumReservedValues=*/2, "p1", BB3);
216   PHI1->addIncoming(ConstantInt::get(Int8Ty, 0), BB1);
217   PHI1->addIncoming(ConstantInt::get(Int8Ty, 1), BB2);
218   auto *PHI2 = PHINode::Create(Int8Ty, /*NumReservedValues=*/2, "p2", BB3);
219   PHI2->addIncoming(ConstantInt::get(Int8Ty, 1), BB1);
220   PHI2->addIncoming(ConstantInt::get(Int8Ty, 0), BB2);
221   auto *RI = ReturnInst::Create(Ctx, BB3);
222 
223   // Now we split the block with PHI nodes, making sure they're all updated.
224   Value *Cond = ConstantInt::getFalse(Ctx);
225   SBOp.BuilderFunc({Cond}, RI);
226 
227   // Make sure the PHIs are updated with a value for the third incoming edge.
228   EXPECT_THAT(PHI1->getNumIncomingValues(), Eq(3u));
229   EXPECT_THAT(PHI2->getNumIncomingValues(), Eq(3u));
230   EXPECT_FALSE(verifyModule(M, &errs()));
231 }
232 
233 TEST(OperationsTest, GEP) {
234   LLVMContext Ctx;
235 
236   Type *Int8PtrTy = Type::getInt8PtrTy(Ctx);
237   Type *Int32Ty = Type::getInt32Ty(Ctx);
238 
239   Module M("M", Ctx);
240   Function *F = Function::Create(FunctionType::get(Type::getVoidTy(Ctx), {},
241                                                    /*isVarArg=*/false),
242                                  GlobalValue::ExternalLinkage, "f", &M);
243   auto *BB = BasicBlock::Create(Ctx, "BB", F);
244   auto *RI = ReturnInst::Create(Ctx, BB);
245 
246   auto GEPOp = fuzzerop::gepDescriptor(1);
247   EXPECT_TRUE(GEPOp.SourcePreds[0].matches({}, UndefValue::get(Int8PtrTy)));
248   EXPECT_TRUE(GEPOp.SourcePreds[1].matches({UndefValue::get(Int8PtrTy)},
249                                            ConstantInt::get(Int32Ty, 0)));
250 
251   GEPOp.BuilderFunc({UndefValue::get(Int8PtrTy), ConstantInt::get(Int32Ty, 0)},
252                     RI);
253   EXPECT_FALSE(verifyModule(M, &errs()));
254 }
255 
256 TEST(OperationsTest, ExtractAndInsertValue) {
257   LLVMContext Ctx;
258 
259   Type *Int8PtrTy = Type::getInt8PtrTy(Ctx);
260   Type *Int32Ty = Type::getInt32Ty(Ctx);
261   Type *Int64Ty = Type::getInt64Ty(Ctx);
262 
263   Type *StructTy = StructType::create(Ctx, {Int8PtrTy, Int32Ty});
264   Type *OpaqueTy = StructType::create(Ctx, "OpaqueStruct");
265   Type *ArrayTy = ArrayType::get(Int64Ty, 4);
266   Type *VectorTy = VectorType::get(Int32Ty, 2);
267 
268   auto EVOp = fuzzerop::extractValueDescriptor(1);
269   auto IVOp = fuzzerop::insertValueDescriptor(1);
270 
271   // Sanity check the source preds.
272   Constant *SVal = UndefValue::get(StructTy);
273   Constant *OVal = UndefValue::get(OpaqueTy);
274   Constant *AVal = UndefValue::get(ArrayTy);
275   Constant *VVal = UndefValue::get(VectorTy);
276 
277   EXPECT_TRUE(EVOp.SourcePreds[0].matches({}, SVal));
278   EXPECT_TRUE(EVOp.SourcePreds[0].matches({}, OVal));
279   EXPECT_TRUE(EVOp.SourcePreds[0].matches({}, AVal));
280   EXPECT_FALSE(EVOp.SourcePreds[0].matches({}, VVal));
281   EXPECT_TRUE(IVOp.SourcePreds[0].matches({}, SVal));
282   EXPECT_TRUE(IVOp.SourcePreds[0].matches({}, OVal));
283   EXPECT_TRUE(IVOp.SourcePreds[0].matches({}, AVal));
284   EXPECT_FALSE(IVOp.SourcePreds[0].matches({}, VVal));
285 
286   // Make sure we're range checking appropriately.
287   EXPECT_TRUE(
288       EVOp.SourcePreds[1].matches({SVal}, ConstantInt::get(Int32Ty, 0)));
289   EXPECT_TRUE(
290       EVOp.SourcePreds[1].matches({SVal}, ConstantInt::get(Int32Ty, 1)));
291   EXPECT_FALSE(
292       EVOp.SourcePreds[1].matches({SVal}, ConstantInt::get(Int32Ty, 2)));
293   EXPECT_FALSE(
294       EVOp.SourcePreds[1].matches({OVal}, ConstantInt::get(Int32Ty, 0)));
295   EXPECT_FALSE(
296       EVOp.SourcePreds[1].matches({OVal}, ConstantInt::get(Int32Ty, 65536)));
297   EXPECT_TRUE(
298       EVOp.SourcePreds[1].matches({AVal}, ConstantInt::get(Int32Ty, 0)));
299   EXPECT_TRUE(
300       EVOp.SourcePreds[1].matches({AVal}, ConstantInt::get(Int32Ty, 3)));
301   EXPECT_FALSE(
302       EVOp.SourcePreds[1].matches({AVal}, ConstantInt::get(Int32Ty, 4)));
303 
304   EXPECT_THAT(
305       EVOp.SourcePreds[1].generate({SVal}, {}),
306       ElementsAre(ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, 1)));
307 
308   // InsertValue should accept any type in the struct, but only in positions
309   // where it makes sense.
310   EXPECT_TRUE(IVOp.SourcePreds[1].matches({SVal}, UndefValue::get(Int8PtrTy)));
311   EXPECT_TRUE(IVOp.SourcePreds[1].matches({SVal}, UndefValue::get(Int32Ty)));
312   EXPECT_FALSE(IVOp.SourcePreds[1].matches({SVal}, UndefValue::get(Int64Ty)));
313   EXPECT_FALSE(IVOp.SourcePreds[2].matches({SVal, UndefValue::get(Int32Ty)},
314                                            ConstantInt::get(Int32Ty, 0)));
315   EXPECT_TRUE(IVOp.SourcePreds[2].matches({SVal, UndefValue::get(Int32Ty)},
316                                           ConstantInt::get(Int32Ty, 1)));
317 
318   EXPECT_THAT(IVOp.SourcePreds[1].generate({SVal}, {}),
319               Each(AnyOf(HasType(Int32Ty), HasType(Int8PtrTy))));
320   EXPECT_THAT(
321       IVOp.SourcePreds[2].generate({SVal, ConstantInt::get(Int32Ty, 0)}, {}),
322       ElementsAre(ConstantInt::get(Int32Ty, 1)));
323 }
324