|
13 | 13 | #include "llvm/FuzzMutate/IRMutator.h"
|
14 | 14 | #include "llvm/FuzzMutate/OpDescriptor.h"
|
15 | 15 | #include "llvm/FuzzMutate/Operations.h"
|
| 16 | +#include "llvm/FuzzMutate/Random.h" |
16 | 17 | #include "llvm/IR/Constants.h"
|
17 | 18 | #include "llvm/IR/Instructions.h"
|
18 | 19 | #include "llvm/IR/LLVMContext.h"
|
@@ -292,4 +293,49 @@ TEST(RandomIRBuilderTest, SwiftError) {
|
292 | 293 | }
|
293 | 294 | }
|
294 | 295 |
|
| 296 | +TEST(RandomIRBuilderTest, dontConnectToSwitch) { |
| 297 | + // Check that we never put anything into switch's case branch |
| 298 | + // If we accidently put a variable, the module is invalid. |
| 299 | + LLVMContext Ctx; |
| 300 | + const char *SourceCode = "\n\ |
| 301 | + define void @test(i1 %C1, i1 %C2, i32 %I, i32 %J) { \n\ |
| 302 | + Entry: \n\ |
| 303 | + %I.1 = add i32 %I, 42 \n\ |
| 304 | + %J.1 = add i32 %J, 42 \n\ |
| 305 | + %IJ = add i32 %I, %J \n\ |
| 306 | + switch i32 %I, label %Default [ \n\ |
| 307 | + i32 1, label %OnOne \n\ |
| 308 | + ] \n\ |
| 309 | + Default: \n\ |
| 310 | + %CIEqJ = icmp eq i32 %I.1, %J.1 \n\ |
| 311 | + %CISltJ = icmp slt i32 %I.1, %J.1 \n\ |
| 312 | + %CAnd = and i1 %C1, %C2 \n\ |
| 313 | + br i1 %CIEqJ, label %Default, label %Exit \n\ |
| 314 | + OnOne: \n\ |
| 315 | + br i1 %C1, label %OnOne, label %Exit \n\ |
| 316 | + Exit: \n\ |
| 317 | + ret void \n\ |
| 318 | + }"; |
| 319 | + |
| 320 | + std::vector<Type *> Types = {Type::getInt32Ty(Ctx), Type::getInt1Ty(Ctx)}; |
| 321 | + RandomIRBuilder IB(Seed, Types); |
| 322 | + for (int i = 0; i < 20; i++) { |
| 323 | + std::unique_ptr<Module> M = parseAssembly(SourceCode, Ctx); |
| 324 | + Function &F = *M->getFunction("test"); |
| 325 | + auto RS = makeSampler(IB.Rand, make_pointer_range(F)); |
| 326 | + BasicBlock *BB = RS.getSelection(); |
| 327 | + SmallVector<Instruction *, 32> Insts; |
| 328 | + for (auto I = BB->getFirstInsertionPt(), E = BB->end(); I != E; ++I) |
| 329 | + Insts.push_back(&*I); |
| 330 | + if (Insts.size() < 2) |
| 331 | + continue; |
| 332 | + // Choose an instruction and connect to later operations. |
| 333 | + size_t IP = uniform<size_t>(IB.Rand, 1, Insts.size() - 1); |
| 334 | + Instruction *Inst = Insts[IP - 1]; |
| 335 | + auto ConnectAfter = makeArrayRef(Insts).slice(IP); |
| 336 | + IB.connectToSink(*BB, ConnectAfter, Inst); |
| 337 | + ASSERT_FALSE(verifyModule(*M, &errs())); |
| 338 | + } |
| 339 | +} |
| 340 | + |
295 | 341 | } // namespace
|
0 commit comments