1 //===- OperationsTest.cpp - Tests for fuzzer operations -------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/FuzzMutate/Operations.h"
10 #include "llvm/AsmParser/Parser.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 "llvm/Support/SourceMgr.h"
17 #include "gmock/gmock.h"
18 #include "gtest/gtest.h"
21 // Define some pretty printers to help with debugging failures.
23 void PrintTo(Type
*T
, ::std::ostream
*OS
) {
24 raw_os_ostream
ROS(*OS
);
28 void PrintTo(BasicBlock
*BB
, ::std::ostream
*OS
) {
29 raw_os_ostream
ROS(*OS
);
30 ROS
<< BB
<< " (" << BB
->getName() << ")";
33 void PrintTo(Value
*V
, ::std::ostream
*OS
) {
34 raw_os_ostream
ROS(*OS
);
39 void PrintTo(Constant
*C
, ::std::ostream
*OS
) { PrintTo(cast
<Value
>(C
), OS
); }
47 using testing::ElementsAre
;
52 using testing::NotNull
;
53 using testing::PrintToString
;
54 using testing::SizeIs
;
57 std::unique_ptr
<Module
> parseAssembly(
58 const char *Assembly
, LLVMContext
&Context
) {
61 std::unique_ptr
<Module
> M
= parseAssemblyString(Assembly
, Error
, Context
);
64 raw_string_ostream
OS(ErrMsg
);
67 assert(M
&& !verifyModule(*M
, &errs()));
71 MATCHER_P(TypesMatch
, V
, "has type " + PrintToString(V
->getType())) {
72 return arg
->getType() == V
->getType();
75 MATCHER_P(HasType
, T
, "") { return arg
->getType() == T
; }
77 TEST(OperationsTest
, SourcePreds
) {
78 using namespace llvm::fuzzerop
;
82 Constant
*i1
= ConstantInt::getFalse(Ctx
);
83 Constant
*i8
= ConstantInt::get(Type::getInt8Ty(Ctx
), 3);
84 Constant
*i16
= ConstantInt::get(Type::getInt16Ty(Ctx
), 1 << 15);
85 Constant
*i32
= ConstantInt::get(Type::getInt32Ty(Ctx
), 0);
86 Constant
*i64
= ConstantInt::get(Type::getInt64Ty(Ctx
),
87 std::numeric_limits
<uint64_t>::max());
88 Constant
*f16
= ConstantFP::getInfinity(Type::getHalfTy(Ctx
));
89 Constant
*f32
= ConstantFP::get(Type::getFloatTy(Ctx
), 0.0);
90 Constant
*f64
= ConstantFP::get(Type::getDoubleTy(Ctx
), 123.45);
92 ConstantStruct::get(StructType::create(Ctx
, "OpaqueStruct"));
94 ConstantArray::get(ArrayType::get(i32
->getType(), 2), {i32
, i32
});
95 Constant
*v8i8
= ConstantVector::getSplat(8, i8
);
96 Constant
*v4f16
= ConstantVector::getSplat(4, f16
);
98 ConstantPointerNull::get(PointerType::get(i32
->getType(), 0));
100 auto OnlyI32
= onlyType(i32
->getType());
101 EXPECT_TRUE(OnlyI32
.matches({}, i32
));
102 EXPECT_FALSE(OnlyI32
.matches({}, i64
));
103 EXPECT_FALSE(OnlyI32
.matches({}, p0i32
));
104 EXPECT_FALSE(OnlyI32
.matches({}, a
));
106 EXPECT_THAT(OnlyI32
.generate({}, {}),
107 AllOf(SizeIs(Ge(1u)), Each(TypesMatch(i32
))));
109 auto AnyType
= anyType();
110 EXPECT_TRUE(AnyType
.matches({}, i1
));
111 EXPECT_TRUE(AnyType
.matches({}, f64
));
112 EXPECT_TRUE(AnyType
.matches({}, s
));
113 EXPECT_TRUE(AnyType
.matches({}, v8i8
));
114 EXPECT_TRUE(AnyType
.matches({}, p0i32
));
117 AnyType
.generate({}, {i32
->getType(), f16
->getType(), v8i8
->getType()}),
118 Each(AnyOf(TypesMatch(i32
), TypesMatch(f16
), TypesMatch(v8i8
))));
120 auto AnyInt
= anyIntType();
121 EXPECT_TRUE(AnyInt
.matches({}, i1
));
122 EXPECT_TRUE(AnyInt
.matches({}, i64
));
123 EXPECT_FALSE(AnyInt
.matches({}, f32
));
124 EXPECT_FALSE(AnyInt
.matches({}, v4f16
));
127 AnyInt
.generate({}, {i32
->getType(), f16
->getType(), v8i8
->getType()}),
128 AllOf(SizeIs(Ge(1u)), Each(TypesMatch(i32
))));
130 auto AnyFP
= anyFloatType();
131 EXPECT_TRUE(AnyFP
.matches({}, f16
));
132 EXPECT_TRUE(AnyFP
.matches({}, f32
));
133 EXPECT_FALSE(AnyFP
.matches({}, i16
));
134 EXPECT_FALSE(AnyFP
.matches({}, p0i32
));
135 EXPECT_FALSE(AnyFP
.matches({}, v4f16
));
138 AnyFP
.generate({}, {i32
->getType(), f16
->getType(), v8i8
->getType()}),
139 AllOf(SizeIs(Ge(1u)), Each(TypesMatch(f16
))));
141 auto AnyPtr
= anyPtrType();
142 EXPECT_TRUE(AnyPtr
.matches({}, p0i32
));
143 EXPECT_FALSE(AnyPtr
.matches({}, i8
));
144 EXPECT_FALSE(AnyPtr
.matches({}, a
));
145 EXPECT_FALSE(AnyPtr
.matches({}, v8i8
));
147 auto isPointer
= [](Value
*V
) { return V
->getType()->isPointerTy(); };
149 AnyPtr
.generate({}, {i32
->getType(), f16
->getType(), v8i8
->getType()}),
150 AllOf(SizeIs(Ge(3u)), Each(Truly(isPointer
))));
152 auto AnyVec
= anyVectorType();
153 EXPECT_TRUE(AnyVec
.matches({}, v8i8
));
154 EXPECT_TRUE(AnyVec
.matches({}, v4f16
));
155 EXPECT_FALSE(AnyVec
.matches({}, i8
));
156 EXPECT_FALSE(AnyVec
.matches({}, a
));
157 EXPECT_FALSE(AnyVec
.matches({}, s
));
159 EXPECT_THAT(AnyVec
.generate({}, {v8i8
->getType()}),
160 ElementsAre(TypesMatch(v8i8
)));
162 auto First
= matchFirstType();
163 EXPECT_TRUE(First
.matches({i8
}, i8
));
164 EXPECT_TRUE(First
.matches({s
, a
}, s
));
165 EXPECT_FALSE(First
.matches({f16
}, f32
));
166 EXPECT_FALSE(First
.matches({v4f16
, f64
}, f64
));
168 EXPECT_THAT(First
.generate({i8
}, {}), Each(TypesMatch(i8
)));
169 EXPECT_THAT(First
.generate({f16
}, {i8
->getType()}),
170 Each(TypesMatch(f16
)));
171 EXPECT_THAT(First
.generate({v8i8
, i32
}, {}), Each(TypesMatch(v8i8
)));
174 TEST(OperationsTest
, SplitBlock
) {
178 Function
*F
= Function::Create(FunctionType::get(Type::getVoidTy(Ctx
), {},
180 GlobalValue::ExternalLinkage
, "f", &M
);
181 auto SBOp
= fuzzerop::splitBlockDescriptor(1);
183 // Create a block with only a return and split it on the return.
184 auto *BB
= BasicBlock::Create(Ctx
, "BB", F
);
185 auto *RI
= ReturnInst::Create(Ctx
, BB
);
186 SBOp
.BuilderFunc({UndefValue::get(Type::getInt1Ty(Ctx
))}, RI
);
188 // We should end up with an unconditional branch from BB to BB1, and the
189 // return ends up in BB1.
190 auto *UncondBr
= cast
<BranchInst
>(BB
->getTerminator());
191 ASSERT_TRUE(UncondBr
->isUnconditional());
192 auto *BB1
= UncondBr
->getSuccessor(0);
193 ASSERT_THAT(RI
->getParent(), Eq(BB1
));
195 // Now add an instruction to BB1 and split on that.
196 auto *AI
= new AllocaInst(Type::getInt8Ty(Ctx
), 0, "a", RI
);
197 Value
*Cond
= ConstantInt::getFalse(Ctx
);
198 SBOp
.BuilderFunc({Cond
}, AI
);
200 // We should end up with a loop back on BB1 and the instruction we split on
202 auto *CondBr
= cast
<BranchInst
>(BB1
->getTerminator());
203 EXPECT_THAT(CondBr
->getCondition(), Eq(Cond
));
204 ASSERT_THAT(CondBr
->getNumSuccessors(), Eq(2u));
205 ASSERT_THAT(CondBr
->getSuccessor(0), Eq(BB1
));
206 auto *BB2
= CondBr
->getSuccessor(1);
207 EXPECT_THAT(AI
->getParent(), Eq(BB2
));
208 EXPECT_THAT(RI
->getParent(), Eq(BB2
));
210 EXPECT_FALSE(verifyModule(M
, &errs()));
213 TEST(OperationsTest
, SplitEHBlock
) {
214 // Check that we will not try to branch back to the landingpad block using
215 // regular branch instruction
218 const char *SourceCode
=
220 "declare i32 @personality_function()"
221 "define i32* @test() personality i32 ()* @personality_function {\n"
223 " %val = invoke i32* @f()\n"
224 " to label %normal unwind label %exceptional\n"
228 " %landing_pad4 = landingpad token cleanup\n"
231 auto M
= parseAssembly(SourceCode
, Ctx
);
233 // Get the landingpad block
234 BasicBlock
&BB
= *std::next(M
->getFunction("test")->begin(), 2);
236 fuzzerop::OpDescriptor Descr
= fuzzerop::splitBlockDescriptor(1);
238 Descr
.BuilderFunc({ConstantInt::getTrue(Ctx
)},&*BB
.getFirstInsertionPt());
239 ASSERT_TRUE(!verifyModule(*M
, &errs()));
242 TEST(OperationsTest
, SplitBlockWithPhis
) {
245 Type
*Int8Ty
= Type::getInt8Ty(Ctx
);
248 Function
*F
= Function::Create(FunctionType::get(Type::getVoidTy(Ctx
), {},
250 GlobalValue::ExternalLinkage
, "f", &M
);
251 auto SBOp
= fuzzerop::splitBlockDescriptor(1);
253 // Create 3 blocks with an if-then branch.
254 auto *BB1
= BasicBlock::Create(Ctx
, "BB1", F
);
255 auto *BB2
= BasicBlock::Create(Ctx
, "BB2", F
);
256 auto *BB3
= BasicBlock::Create(Ctx
, "BB3", F
);
257 BranchInst::Create(BB2
, BB3
, ConstantInt::getFalse(Ctx
), BB1
);
258 BranchInst::Create(BB3
, BB2
);
260 // Set up phi nodes selecting values for the incoming edges.
261 auto *PHI1
= PHINode::Create(Int8Ty
, /*NumReservedValues=*/2, "p1", BB3
);
262 PHI1
->addIncoming(ConstantInt::get(Int8Ty
, 0), BB1
);
263 PHI1
->addIncoming(ConstantInt::get(Int8Ty
, 1), BB2
);
264 auto *PHI2
= PHINode::Create(Int8Ty
, /*NumReservedValues=*/2, "p2", BB3
);
265 PHI2
->addIncoming(ConstantInt::get(Int8Ty
, 1), BB1
);
266 PHI2
->addIncoming(ConstantInt::get(Int8Ty
, 0), BB2
);
267 auto *RI
= ReturnInst::Create(Ctx
, BB3
);
269 // Now we split the block with PHI nodes, making sure they're all updated.
270 Value
*Cond
= ConstantInt::getFalse(Ctx
);
271 SBOp
.BuilderFunc({Cond
}, RI
);
273 // Make sure the PHIs are updated with a value for the third incoming edge.
274 EXPECT_THAT(PHI1
->getNumIncomingValues(), Eq(3u));
275 EXPECT_THAT(PHI2
->getNumIncomingValues(), Eq(3u));
276 EXPECT_FALSE(verifyModule(M
, &errs()));
279 TEST(OperationsTest
, GEP
) {
282 Type
*Int8PtrTy
= Type::getInt8PtrTy(Ctx
);
283 Type
*Int32Ty
= Type::getInt32Ty(Ctx
);
286 Function
*F
= Function::Create(FunctionType::get(Type::getVoidTy(Ctx
), {},
288 GlobalValue::ExternalLinkage
, "f", &M
);
289 auto *BB
= BasicBlock::Create(Ctx
, "BB", F
);
290 auto *RI
= ReturnInst::Create(Ctx
, BB
);
292 auto GEPOp
= fuzzerop::gepDescriptor(1);
293 EXPECT_TRUE(GEPOp
.SourcePreds
[0].matches({}, UndefValue::get(Int8PtrTy
)));
294 EXPECT_TRUE(GEPOp
.SourcePreds
[1].matches({UndefValue::get(Int8PtrTy
)},
295 ConstantInt::get(Int32Ty
, 0)));
297 GEPOp
.BuilderFunc({UndefValue::get(Int8PtrTy
), ConstantInt::get(Int32Ty
, 0)},
299 EXPECT_FALSE(verifyModule(M
, &errs()));
303 TEST(OperationsTest
, GEPPointerOperand
) {
304 // Check that we only pick sized pointers for the GEP instructions
307 const char *SourceCode
=
308 "declare void @f()\n"
309 "define void @test() {\n"
310 " %v = bitcast void ()* @f to i64 (i8 addrspace(4)*)*\n"
311 " %a = alloca i64, i32 10\n"
314 auto M
= parseAssembly(SourceCode
, Ctx
);
316 fuzzerop::OpDescriptor Descr
= fuzzerop::gepDescriptor(1);
318 // Get first basic block of the test function
319 Function
&F
= *M
->getFunction("test");
320 BasicBlock
&BB
= *F
.begin();
323 ASSERT_FALSE(Descr
.SourcePreds
[0].matches({}, &*BB
.begin()));
326 ASSERT_TRUE(Descr
.SourcePreds
[0].matches({}, &*std::next(BB
.begin())));
329 TEST(OperationsTest
, ExtractAndInsertValue
) {
332 Type
*Int8PtrTy
= Type::getInt8PtrTy(Ctx
);
333 Type
*Int32Ty
= Type::getInt32Ty(Ctx
);
334 Type
*Int64Ty
= Type::getInt64Ty(Ctx
);
336 Type
*StructTy
= StructType::create(Ctx
, {Int8PtrTy
, Int32Ty
});
337 Type
*OpaqueTy
= StructType::create(Ctx
, "OpaqueStruct");
338 Type
*ZeroSizedArrayTy
= ArrayType::get(Int64Ty
, 0);
339 Type
*ArrayTy
= ArrayType::get(Int64Ty
, 4);
340 Type
*VectorTy
= VectorType::get(Int32Ty
, 2);
342 auto EVOp
= fuzzerop::extractValueDescriptor(1);
343 auto IVOp
= fuzzerop::insertValueDescriptor(1);
345 // Sanity check the source preds.
346 Constant
*SVal
= UndefValue::get(StructTy
);
347 Constant
*OVal
= UndefValue::get(OpaqueTy
);
348 Constant
*AVal
= UndefValue::get(ArrayTy
);
349 Constant
*ZAVal
= UndefValue::get(ZeroSizedArrayTy
);
350 Constant
*VVal
= UndefValue::get(VectorTy
);
352 EXPECT_TRUE(EVOp
.SourcePreds
[0].matches({}, SVal
));
353 EXPECT_FALSE(EVOp
.SourcePreds
[0].matches({}, OVal
));
354 EXPECT_TRUE(EVOp
.SourcePreds
[0].matches({}, AVal
));
355 EXPECT_FALSE(EVOp
.SourcePreds
[0].matches({}, VVal
));
356 EXPECT_TRUE(IVOp
.SourcePreds
[0].matches({}, SVal
));
357 EXPECT_FALSE(IVOp
.SourcePreds
[0].matches({}, OVal
));
358 EXPECT_TRUE(IVOp
.SourcePreds
[0].matches({}, AVal
));
359 EXPECT_FALSE(IVOp
.SourcePreds
[0].matches({}, VVal
));
361 // Don't consider zero sized arrays as viable sources
362 EXPECT_FALSE(EVOp
.SourcePreds
[0].matches({}, ZAVal
));
363 EXPECT_FALSE(IVOp
.SourcePreds
[0].matches({}, ZAVal
));
365 // Make sure we're range checking appropriately.
367 EVOp
.SourcePreds
[1].matches({SVal
}, ConstantInt::get(Int32Ty
, 0)));
369 EVOp
.SourcePreds
[1].matches({SVal
}, ConstantInt::get(Int32Ty
, 1)));
371 EVOp
.SourcePreds
[1].matches({SVal
}, ConstantInt::get(Int32Ty
, 2)));
373 EVOp
.SourcePreds
[1].matches({OVal
}, ConstantInt::get(Int32Ty
, 0)));
375 EVOp
.SourcePreds
[1].matches({OVal
}, ConstantInt::get(Int32Ty
, 65536)));
377 EVOp
.SourcePreds
[1].matches({AVal
}, ConstantInt::get(Int32Ty
, 0)));
379 EVOp
.SourcePreds
[1].matches({AVal
}, ConstantInt::get(Int32Ty
, 3)));
381 EVOp
.SourcePreds
[1].matches({AVal
}, ConstantInt::get(Int32Ty
, 4)));
384 EVOp
.SourcePreds
[1].generate({SVal
}, {}),
385 ElementsAre(ConstantInt::get(Int32Ty
, 0), ConstantInt::get(Int32Ty
, 1)));
387 // InsertValue should accept any type in the struct, but only in positions
388 // where it makes sense.
389 EXPECT_TRUE(IVOp
.SourcePreds
[1].matches({SVal
}, UndefValue::get(Int8PtrTy
)));
390 EXPECT_TRUE(IVOp
.SourcePreds
[1].matches({SVal
}, UndefValue::get(Int32Ty
)));
391 EXPECT_FALSE(IVOp
.SourcePreds
[1].matches({SVal
}, UndefValue::get(Int64Ty
)));
392 EXPECT_FALSE(IVOp
.SourcePreds
[2].matches({SVal
, UndefValue::get(Int32Ty
)},
393 ConstantInt::get(Int32Ty
, 0)));
394 EXPECT_TRUE(IVOp
.SourcePreds
[2].matches({SVal
, UndefValue::get(Int32Ty
)},
395 ConstantInt::get(Int32Ty
, 1)));
397 EXPECT_THAT(IVOp
.SourcePreds
[1].generate({SVal
}, {}),
398 Each(AnyOf(HasType(Int32Ty
), HasType(Int8PtrTy
))));
400 IVOp
.SourcePreds
[2].generate({SVal
, ConstantInt::get(Int32Ty
, 0)}, {}),
401 ElementsAre(ConstantInt::get(Int32Ty
, 1)));