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

source code of llvm/unittests/FuzzMutate/OperationsTest.cpp