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/AsmParser/Parser.h"
12 #include "llvm/FuzzMutate/OpDescriptor.h"
13 #include "llvm/IR/Constants.h"
14 #include "llvm/IR/Instructions.h"
15 #include "llvm/IR/Module.h"
16 #include "llvm/IR/Verifier.h"
17 #include "llvm/Support/SourceMgr.h"
18 #include "gmock/gmock.h"
19 #include "gtest/gtest.h"
20 #include <iostream>
21
22 // Define some pretty printers to help with debugging failures.
23 namespace llvm {
PrintTo(Type * T,::std::ostream * OS)24 void PrintTo(Type *T, ::std::ostream *OS) {
25 raw_os_ostream ROS(*OS);
26 T->print(ROS);
27 }
28
PrintTo(BasicBlock * BB,::std::ostream * OS)29 void PrintTo(BasicBlock *BB, ::std::ostream *OS) {
30 raw_os_ostream ROS(*OS);
31 ROS << BB << " (" << BB->getName() << ")";
32 }
33
PrintTo(Value * V,::std::ostream * OS)34 void PrintTo(Value *V, ::std::ostream *OS) {
35 raw_os_ostream ROS(*OS);
36 ROS << V << " (";
37 V->print(ROS);
38 ROS << ")";
39 }
PrintTo(Constant * C,::std::ostream * OS)40 void PrintTo(Constant *C, ::std::ostream *OS) { PrintTo(cast<Value>(C), OS); }
41
42 } // namespace llvm
43
44 using namespace llvm;
45
46 using testing::AllOf;
47 using testing::AnyOf;
48 using testing::ElementsAre;
49 using testing::Eq;
50 using testing::Ge;
51 using testing::Each;
52 using testing::Truly;
53 using testing::NotNull;
54 using testing::PrintToString;
55 using testing::SizeIs;
56
57 namespace {
parseAssembly(const char * Assembly,LLVMContext & Context)58 std::unique_ptr<Module> parseAssembly(
59 const char *Assembly, LLVMContext &Context) {
60
61 SMDiagnostic Error;
62 std::unique_ptr<Module> M = parseAssemblyString(Assembly, Error, Context);
63
64 std::string ErrMsg;
65 raw_string_ostream OS(ErrMsg);
66 Error.print("", OS);
67
68 assert(M && !verifyModule(*M, &errs()));
69 return M;
70 }
71
72 MATCHER_P(TypesMatch, V, "has type " + PrintToString(V->getType())) {
73 return arg->getType() == V->getType();
74 }
75
76 MATCHER_P(HasType, T, "") { return arg->getType() == T; }
77
TEST(OperationsTest,SourcePreds)78 TEST(OperationsTest, SourcePreds) {
79 using namespace llvm::fuzzerop;
80
81 LLVMContext Ctx;
82
83 Constant *i1 = ConstantInt::getFalse(Ctx);
84 Constant *i8 = ConstantInt::get(Type::getInt8Ty(Ctx), 3);
85 Constant *i16 = ConstantInt::get(Type::getInt16Ty(Ctx), 1 << 15);
86 Constant *i32 = ConstantInt::get(Type::getInt32Ty(Ctx), 0);
87 Constant *i64 = ConstantInt::get(Type::getInt64Ty(Ctx),
88 std::numeric_limits<uint64_t>::max());
89 Constant *f16 = ConstantFP::getInfinity(Type::getHalfTy(Ctx));
90 Constant *f32 = ConstantFP::get(Type::getFloatTy(Ctx), 0.0);
91 Constant *f64 = ConstantFP::get(Type::getDoubleTy(Ctx), 123.45);
92 Constant *s =
93 ConstantStruct::get(StructType::create(Ctx, "OpaqueStruct"));
94 Constant *a =
95 ConstantArray::get(ArrayType::get(i32->getType(), 2), {i32, i32});
96 Constant *v8i8 = ConstantVector::getSplat(8, i8);
97 Constant *v4f16 = ConstantVector::getSplat(4, f16);
98 Constant *p0i32 =
99 ConstantPointerNull::get(PointerType::get(i32->getType(), 0));
100
101 auto OnlyI32 = onlyType(i32->getType());
102 EXPECT_TRUE(OnlyI32.matches({}, i32));
103 EXPECT_FALSE(OnlyI32.matches({}, i64));
104 EXPECT_FALSE(OnlyI32.matches({}, p0i32));
105 EXPECT_FALSE(OnlyI32.matches({}, a));
106
107 EXPECT_THAT(OnlyI32.generate({}, {}),
108 AllOf(SizeIs(Ge(1u)), Each(TypesMatch(i32))));
109
110 auto AnyType = anyType();
111 EXPECT_TRUE(AnyType.matches({}, i1));
112 EXPECT_TRUE(AnyType.matches({}, f64));
113 EXPECT_TRUE(AnyType.matches({}, s));
114 EXPECT_TRUE(AnyType.matches({}, v8i8));
115 EXPECT_TRUE(AnyType.matches({}, p0i32));
116
117 EXPECT_THAT(
118 AnyType.generate({}, {i32->getType(), f16->getType(), v8i8->getType()}),
119 Each(AnyOf(TypesMatch(i32), TypesMatch(f16), TypesMatch(v8i8))));
120
121 auto AnyInt = anyIntType();
122 EXPECT_TRUE(AnyInt.matches({}, i1));
123 EXPECT_TRUE(AnyInt.matches({}, i64));
124 EXPECT_FALSE(AnyInt.matches({}, f32));
125 EXPECT_FALSE(AnyInt.matches({}, v4f16));
126
127 EXPECT_THAT(
128 AnyInt.generate({}, {i32->getType(), f16->getType(), v8i8->getType()}),
129 AllOf(SizeIs(Ge(1u)), Each(TypesMatch(i32))));
130
131 auto AnyFP = anyFloatType();
132 EXPECT_TRUE(AnyFP.matches({}, f16));
133 EXPECT_TRUE(AnyFP.matches({}, f32));
134 EXPECT_FALSE(AnyFP.matches({}, i16));
135 EXPECT_FALSE(AnyFP.matches({}, p0i32));
136 EXPECT_FALSE(AnyFP.matches({}, v4f16));
137
138 EXPECT_THAT(
139 AnyFP.generate({}, {i32->getType(), f16->getType(), v8i8->getType()}),
140 AllOf(SizeIs(Ge(1u)), Each(TypesMatch(f16))));
141
142 auto AnyPtr = anyPtrType();
143 EXPECT_TRUE(AnyPtr.matches({}, p0i32));
144 EXPECT_FALSE(AnyPtr.matches({}, i8));
145 EXPECT_FALSE(AnyPtr.matches({}, a));
146 EXPECT_FALSE(AnyPtr.matches({}, v8i8));
147
148 auto isPointer = [](Value *V) { return V->getType()->isPointerTy(); };
149 EXPECT_THAT(
150 AnyPtr.generate({}, {i32->getType(), f16->getType(), v8i8->getType()}),
151 AllOf(SizeIs(Ge(3u)), Each(Truly(isPointer))));
152
153 auto AnyVec = anyVectorType();
154 EXPECT_TRUE(AnyVec.matches({}, v8i8));
155 EXPECT_TRUE(AnyVec.matches({}, v4f16));
156 EXPECT_FALSE(AnyVec.matches({}, i8));
157 EXPECT_FALSE(AnyVec.matches({}, a));
158 EXPECT_FALSE(AnyVec.matches({}, s));
159
160 EXPECT_THAT(AnyVec.generate({}, {v8i8->getType()}),
161 ElementsAre(TypesMatch(v8i8)));
162
163 auto First = matchFirstType();
164 EXPECT_TRUE(First.matches({i8}, i8));
165 EXPECT_TRUE(First.matches({s, a}, s));
166 EXPECT_FALSE(First.matches({f16}, f32));
167 EXPECT_FALSE(First.matches({v4f16, f64}, f64));
168
169 EXPECT_THAT(First.generate({i8}, {}), Each(TypesMatch(i8)));
170 EXPECT_THAT(First.generate({f16}, {i8->getType()}),
171 Each(TypesMatch(f16)));
172 EXPECT_THAT(First.generate({v8i8, i32}, {}), Each(TypesMatch(v8i8)));
173 }
174
TEST(OperationsTest,SplitBlock)175 TEST(OperationsTest, SplitBlock) {
176 LLVMContext Ctx;
177
178 Module M("M", Ctx);
179 Function *F = Function::Create(FunctionType::get(Type::getVoidTy(Ctx), {},
180 /*isVarArg=*/false),
181 GlobalValue::ExternalLinkage, "f", &M);
182 auto SBOp = fuzzerop::splitBlockDescriptor(1);
183
184 // Create a block with only a return and split it on the return.
185 auto *BB = BasicBlock::Create(Ctx, "BB", F);
186 auto *RI = ReturnInst::Create(Ctx, BB);
187 SBOp.BuilderFunc({UndefValue::get(Type::getInt1Ty(Ctx))}, RI);
188
189 // We should end up with an unconditional branch from BB to BB1, and the
190 // return ends up in BB1.
191 auto *UncondBr = cast<BranchInst>(BB->getTerminator());
192 ASSERT_TRUE(UncondBr->isUnconditional());
193 auto *BB1 = UncondBr->getSuccessor(0);
194 ASSERT_THAT(RI->getParent(), Eq(BB1));
195
196 // Now add an instruction to BB1 and split on that.
197 auto *AI = new AllocaInst(Type::getInt8Ty(Ctx), 0, "a", RI);
198 Value *Cond = ConstantInt::getFalse(Ctx);
199 SBOp.BuilderFunc({Cond}, AI);
200
201 // We should end up with a loop back on BB1 and the instruction we split on
202 // moves to BB2.
203 auto *CondBr = cast<BranchInst>(BB1->getTerminator());
204 EXPECT_THAT(CondBr->getCondition(), Eq(Cond));
205 ASSERT_THAT(CondBr->getNumSuccessors(), Eq(2u));
206 ASSERT_THAT(CondBr->getSuccessor(0), Eq(BB1));
207 auto *BB2 = CondBr->getSuccessor(1);
208 EXPECT_THAT(AI->getParent(), Eq(BB2));
209 EXPECT_THAT(RI->getParent(), Eq(BB2));
210
211 EXPECT_FALSE(verifyModule(M, &errs()));
212 }
213
TEST(OperationsTest,SplitEHBlock)214 TEST(OperationsTest, SplitEHBlock) {
215 // Check that we will not try to branch back to the landingpad block using
216 // regular branch instruction
217
218 LLVMContext Ctx;
219 const char *SourceCode =
220 "declare i32* @f()"
221 "declare i32 @personality_function()"
222 "define i32* @test() personality i32 ()* @personality_function {\n"
223 "entry:\n"
224 " %val = invoke i32* @f()\n"
225 " to label %normal unwind label %exceptional\n"
226 "normal:\n"
227 " ret i32* %val\n"
228 "exceptional:\n"
229 " %landing_pad4 = landingpad token cleanup\n"
230 " ret i32* undef\n"
231 "}";
232 auto M = parseAssembly(SourceCode, Ctx);
233
234 // Get the landingpad block
235 BasicBlock &BB = *std::next(M->getFunction("test")->begin(), 2);
236
237 fuzzerop::OpDescriptor Descr = fuzzerop::splitBlockDescriptor(1);
238
239 Descr.BuilderFunc({ConstantInt::getTrue(Ctx)},&*BB.getFirstInsertionPt());
240 ASSERT_TRUE(!verifyModule(*M, &errs()));
241 }
242
TEST(OperationsTest,SplitBlockWithPhis)243 TEST(OperationsTest, SplitBlockWithPhis) {
244 LLVMContext Ctx;
245
246 Type *Int8Ty = Type::getInt8Ty(Ctx);
247
248 Module M("M", Ctx);
249 Function *F = Function::Create(FunctionType::get(Type::getVoidTy(Ctx), {},
250 /*isVarArg=*/false),
251 GlobalValue::ExternalLinkage, "f", &M);
252 auto SBOp = fuzzerop::splitBlockDescriptor(1);
253
254 // Create 3 blocks with an if-then branch.
255 auto *BB1 = BasicBlock::Create(Ctx, "BB1", F);
256 auto *BB2 = BasicBlock::Create(Ctx, "BB2", F);
257 auto *BB3 = BasicBlock::Create(Ctx, "BB3", F);
258 BranchInst::Create(BB2, BB3, ConstantInt::getFalse(Ctx), BB1);
259 BranchInst::Create(BB3, BB2);
260
261 // Set up phi nodes selecting values for the incoming edges.
262 auto *PHI1 = PHINode::Create(Int8Ty, /*NumReservedValues=*/2, "p1", BB3);
263 PHI1->addIncoming(ConstantInt::get(Int8Ty, 0), BB1);
264 PHI1->addIncoming(ConstantInt::get(Int8Ty, 1), BB2);
265 auto *PHI2 = PHINode::Create(Int8Ty, /*NumReservedValues=*/2, "p2", BB3);
266 PHI2->addIncoming(ConstantInt::get(Int8Ty, 1), BB1);
267 PHI2->addIncoming(ConstantInt::get(Int8Ty, 0), BB2);
268 auto *RI = ReturnInst::Create(Ctx, BB3);
269
270 // Now we split the block with PHI nodes, making sure they're all updated.
271 Value *Cond = ConstantInt::getFalse(Ctx);
272 SBOp.BuilderFunc({Cond}, RI);
273
274 // Make sure the PHIs are updated with a value for the third incoming edge.
275 EXPECT_THAT(PHI1->getNumIncomingValues(), Eq(3u));
276 EXPECT_THAT(PHI2->getNumIncomingValues(), Eq(3u));
277 EXPECT_FALSE(verifyModule(M, &errs()));
278 }
279
TEST(OperationsTest,GEP)280 TEST(OperationsTest, GEP) {
281 LLVMContext Ctx;
282
283 Type *Int8PtrTy = Type::getInt8PtrTy(Ctx);
284 Type *Int32Ty = Type::getInt32Ty(Ctx);
285
286 Module M("M", Ctx);
287 Function *F = Function::Create(FunctionType::get(Type::getVoidTy(Ctx), {},
288 /*isVarArg=*/false),
289 GlobalValue::ExternalLinkage, "f", &M);
290 auto *BB = BasicBlock::Create(Ctx, "BB", F);
291 auto *RI = ReturnInst::Create(Ctx, BB);
292
293 auto GEPOp = fuzzerop::gepDescriptor(1);
294 EXPECT_TRUE(GEPOp.SourcePreds[0].matches({}, UndefValue::get(Int8PtrTy)));
295 EXPECT_TRUE(GEPOp.SourcePreds[1].matches({UndefValue::get(Int8PtrTy)},
296 ConstantInt::get(Int32Ty, 0)));
297
298 GEPOp.BuilderFunc({UndefValue::get(Int8PtrTy), ConstantInt::get(Int32Ty, 0)},
299 RI);
300 EXPECT_FALSE(verifyModule(M, &errs()));
301 }
302
303
TEST(OperationsTest,GEPPointerOperand)304 TEST(OperationsTest, GEPPointerOperand) {
305 // Check that we only pick sized pointers for the GEP instructions
306
307 LLVMContext Ctx;
308 const char *SourceCode =
309 "declare void @f()\n"
310 "define void @test() {\n"
311 " %v = bitcast void ()* @f to i64 (i8 addrspace(4)*)*\n"
312 " %a = alloca i64, i32 10\n"
313 " ret void\n"
314 "}";
315 auto M = parseAssembly(SourceCode, Ctx);
316
317 fuzzerop::OpDescriptor Descr = fuzzerop::gepDescriptor(1);
318
319 // Get first basic block of the test function
320 Function &F = *M->getFunction("test");
321 BasicBlock &BB = *F.begin();
322
323 // Don't match %v
324 ASSERT_FALSE(Descr.SourcePreds[0].matches({}, &*BB.begin()));
325
326 // Match %a
327 ASSERT_TRUE(Descr.SourcePreds[0].matches({}, &*std::next(BB.begin())));
328 }
329
TEST(OperationsTest,ExtractAndInsertValue)330 TEST(OperationsTest, ExtractAndInsertValue) {
331 LLVMContext Ctx;
332
333 Type *Int8PtrTy = Type::getInt8PtrTy(Ctx);
334 Type *Int32Ty = Type::getInt32Ty(Ctx);
335 Type *Int64Ty = Type::getInt64Ty(Ctx);
336
337 Type *StructTy = StructType::create(Ctx, {Int8PtrTy, Int32Ty});
338 Type *OpaqueTy = StructType::create(Ctx, "OpaqueStruct");
339 Type *ZeroSizedArrayTy = ArrayType::get(Int64Ty, 0);
340 Type *ArrayTy = ArrayType::get(Int64Ty, 4);
341 Type *VectorTy = VectorType::get(Int32Ty, 2);
342
343 auto EVOp = fuzzerop::extractValueDescriptor(1);
344 auto IVOp = fuzzerop::insertValueDescriptor(1);
345
346 // Sanity check the source preds.
347 Constant *SVal = UndefValue::get(StructTy);
348 Constant *OVal = UndefValue::get(OpaqueTy);
349 Constant *AVal = UndefValue::get(ArrayTy);
350 Constant *ZAVal = UndefValue::get(ZeroSizedArrayTy);
351 Constant *VVal = UndefValue::get(VectorTy);
352
353 EXPECT_TRUE(EVOp.SourcePreds[0].matches({}, SVal));
354 EXPECT_FALSE(EVOp.SourcePreds[0].matches({}, OVal));
355 EXPECT_TRUE(EVOp.SourcePreds[0].matches({}, AVal));
356 EXPECT_FALSE(EVOp.SourcePreds[0].matches({}, VVal));
357 EXPECT_TRUE(IVOp.SourcePreds[0].matches({}, SVal));
358 EXPECT_FALSE(IVOp.SourcePreds[0].matches({}, OVal));
359 EXPECT_TRUE(IVOp.SourcePreds[0].matches({}, AVal));
360 EXPECT_FALSE(IVOp.SourcePreds[0].matches({}, VVal));
361
362 // Don't consider zero sized arrays as viable sources
363 EXPECT_FALSE(EVOp.SourcePreds[0].matches({}, ZAVal));
364 EXPECT_FALSE(IVOp.SourcePreds[0].matches({}, ZAVal));
365
366 // Make sure we're range checking appropriately.
367 EXPECT_TRUE(
368 EVOp.SourcePreds[1].matches({SVal}, ConstantInt::get(Int32Ty, 0)));
369 EXPECT_TRUE(
370 EVOp.SourcePreds[1].matches({SVal}, ConstantInt::get(Int32Ty, 1)));
371 EXPECT_FALSE(
372 EVOp.SourcePreds[1].matches({SVal}, ConstantInt::get(Int32Ty, 2)));
373 EXPECT_FALSE(
374 EVOp.SourcePreds[1].matches({OVal}, ConstantInt::get(Int32Ty, 0)));
375 EXPECT_FALSE(
376 EVOp.SourcePreds[1].matches({OVal}, ConstantInt::get(Int32Ty, 65536)));
377 EXPECT_TRUE(
378 EVOp.SourcePreds[1].matches({AVal}, ConstantInt::get(Int32Ty, 0)));
379 EXPECT_TRUE(
380 EVOp.SourcePreds[1].matches({AVal}, ConstantInt::get(Int32Ty, 3)));
381 EXPECT_FALSE(
382 EVOp.SourcePreds[1].matches({AVal}, ConstantInt::get(Int32Ty, 4)));
383
384 EXPECT_THAT(
385 EVOp.SourcePreds[1].generate({SVal}, {}),
386 ElementsAre(ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, 1)));
387
388 // InsertValue should accept any type in the struct, but only in positions
389 // where it makes sense.
390 EXPECT_TRUE(IVOp.SourcePreds[1].matches({SVal}, UndefValue::get(Int8PtrTy)));
391 EXPECT_TRUE(IVOp.SourcePreds[1].matches({SVal}, UndefValue::get(Int32Ty)));
392 EXPECT_FALSE(IVOp.SourcePreds[1].matches({SVal}, UndefValue::get(Int64Ty)));
393 EXPECT_FALSE(IVOp.SourcePreds[2].matches({SVal, UndefValue::get(Int32Ty)},
394 ConstantInt::get(Int32Ty, 0)));
395 EXPECT_TRUE(IVOp.SourcePreds[2].matches({SVal, UndefValue::get(Int32Ty)},
396 ConstantInt::get(Int32Ty, 1)));
397
398 EXPECT_THAT(IVOp.SourcePreds[1].generate({SVal}, {}),
399 Each(AnyOf(HasType(Int32Ty), HasType(Int8PtrTy))));
400 EXPECT_THAT(
401 IVOp.SourcePreds[2].generate({SVal, ConstantInt::get(Int32Ty, 0)}, {}),
402 ElementsAre(ConstantInt::get(Int32Ty, 1)));
403 }
404
405 }
406