[llvm] c06adae - [FuzzMutate] introduce vector operations, select and fneg into InstInjectorStrategy
Peter Rong via llvm-commits
llvm-commits at lists.llvm.org
Fri Mar 31 17:48:33 PDT 2023
Author: Peter Rong
Date: 2023-03-31T17:48:27-07:00
New Revision: c06adaeba69de173f8eaa16f3449d7e0edaa897f
URL: https://github.com/llvm/llvm-project/commit/c06adaeba69de173f8eaa16f3449d7e0edaa897f
DIFF: https://github.com/llvm/llvm-project/commit/c06adaeba69de173f8eaa16f3449d7e0edaa897f.diff
LOG: [FuzzMutate] introduce vector operations, select and fneg into InstInjectorStrategy
Reviewed By: arsenm
Differential Revision: https://reviews.llvm.org/D139894
Added:
Modified:
llvm/include/llvm/FuzzMutate/OpDescriptor.h
llvm/include/llvm/FuzzMutate/Operations.h
llvm/lib/FuzzMutate/OpDescriptor.cpp
llvm/lib/FuzzMutate/Operations.cpp
llvm/unittests/FuzzMutate/OperationsTest.cpp
llvm/unittests/FuzzMutate/StrategiesTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/FuzzMutate/OpDescriptor.h b/llvm/include/llvm/FuzzMutate/OpDescriptor.h
index 800586da8f2d1..f3b185dfedd8d 100644
--- a/llvm/include/llvm/FuzzMutate/OpDescriptor.h
+++ b/llvm/include/llvm/FuzzMutate/OpDescriptor.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
#include <functional>
@@ -117,6 +118,20 @@ static inline SourcePred anyIntType() {
return {Pred, Make};
}
+static inline SourcePred anyIntOrVecIntType() {
+ auto Pred = [](ArrayRef<Value *>, const Value *V) {
+ return V->getType()->isIntOrIntVectorTy();
+ };
+ return {Pred, std::nullopt};
+}
+
+static inline SourcePred boolOrVecBoolType() {
+ auto Pred = [](ArrayRef<Value *>, const Value *V) {
+ return V->getType()->isIntOrIntVectorTy(1);
+ };
+ return {Pred, std::nullopt};
+}
+
static inline SourcePred anyFloatType() {
auto Pred = [](ArrayRef<Value *>, const Value *V) {
return V->getType()->isFloatingPointTy();
@@ -125,6 +140,13 @@ static inline SourcePred anyFloatType() {
return {Pred, Make};
}
+static inline SourcePred anyFloatOrVecFloatType() {
+ auto Pred = [](ArrayRef<Value *>, const Value *V) {
+ return V->getType()->isFPOrFPVectorTy();
+ };
+ return {Pred, std::nullopt};
+}
+
static inline SourcePred anyPtrType() {
auto Pred = [](ArrayRef<Value *>, const Value *V) {
return V->getType()->isPointerTy() && !V->isSwiftError();
@@ -161,6 +183,54 @@ static inline SourcePred sizedPtrType() {
return {Pred, Make};
}
+static inline SourcePred matchFirstLengthWAnyType() {
+ auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
+ assert(!Cur.empty() && "No first source yet");
+ Type *This = V->getType(), *First = Cur[0]->getType();
+ VectorType *ThisVec = dyn_cast<VectorType>(This);
+ VectorType *FirstVec = dyn_cast<VectorType>(First);
+ if (ThisVec && FirstVec) {
+ return ThisVec->getElementCount() == FirstVec->getElementCount();
+ }
+ return (ThisVec == nullptr) && (FirstVec == nullptr) && (!This->isVoidTy());
+ };
+ auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *> BaseTypes) {
+ assert(!Cur.empty() && "No first source yet");
+ std::vector<Constant *> Result;
+ ElementCount EC;
+ bool isVec = false;
+ if (VectorType *VecTy = dyn_cast<VectorType>(Cur[0]->getType())) {
+ EC = VecTy->getElementCount();
+ isVec = true;
+ }
+ for (Type *T : BaseTypes) {
+ if (VectorType::isValidElementType(T)) {
+ if (isVec)
+ // If the first pred is <i1 x N>, make the result <T x N>
+ makeConstantsWithType(VectorType::get(T, EC), Result);
+ else
+ makeConstantsWithType(T, Result);
+ }
+ }
+ assert(!Result.empty() && "No potential constants.");
+ return Result;
+ };
+ return {Pred, Make};
+}
+
+/// Match values that have the same type as the first source.
+static inline SourcePred matchSecondType() {
+ auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
+ assert((Cur.size() > 1) && "No second source yet");
+ return V->getType() == Cur[1]->getType();
+ };
+ auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) {
+ assert((Cur.size() > 1) && "No second source yet");
+ return makeConstantsWithType(Cur[1]->getType());
+ };
+ return {Pred, Make};
+}
+
static inline SourcePred anyAggregateType() {
auto Pred = [](ArrayRef<Value *>, const Value *V) {
// We can't index zero sized arrays.
diff --git a/llvm/include/llvm/FuzzMutate/Operations.h b/llvm/include/llvm/FuzzMutate/Operations.h
index d2a6180633ea2..84155730a93cd 100644
--- a/llvm/include/llvm/FuzzMutate/Operations.h
+++ b/llvm/include/llvm/FuzzMutate/Operations.h
@@ -28,12 +28,16 @@ void describeFuzzerControlFlowOps(std::vector<fuzzerop::OpDescriptor> &Ops);
void describeFuzzerPointerOps(std::vector<fuzzerop::OpDescriptor> &Ops);
void describeFuzzerAggregateOps(std::vector<fuzzerop::OpDescriptor> &Ops);
void describeFuzzerVectorOps(std::vector<fuzzerop::OpDescriptor> &Ops);
+void describeFuzzerUnaryOperations(std::vector<fuzzerop::OpDescriptor> &Ops);
+void describeFuzzerOtherOps(std::vector<fuzzerop::OpDescriptor> &Ops);
/// @}
namespace fuzzerop {
/// Descriptors for individual operations.
/// @{
+OpDescriptor selectDescriptor(unsigned Weight);
+OpDescriptor fnegDescriptor(unsigned Weight);
OpDescriptor binOpDescriptor(unsigned Weight, Instruction::BinaryOps Op);
OpDescriptor cmpOpDescriptor(unsigned Weight, Instruction::OtherOps CmpOp,
CmpInst::Predicate Pred);
@@ -44,6 +48,7 @@ OpDescriptor insertValueDescriptor(unsigned Weight);
OpDescriptor extractElementDescriptor(unsigned Weight);
OpDescriptor insertElementDescriptor(unsigned Weight);
OpDescriptor shuffleVectorDescriptor(unsigned Weight);
+
/// @}
} // namespace fuzzerop
diff --git a/llvm/lib/FuzzMutate/OpDescriptor.cpp b/llvm/lib/FuzzMutate/OpDescriptor.cpp
index 67d44be8b699b..4baf45284de10 100644
--- a/llvm/lib/FuzzMutate/OpDescriptor.cpp
+++ b/llvm/lib/FuzzMutate/OpDescriptor.cpp
@@ -15,6 +15,9 @@ using namespace fuzzerop;
void fuzzerop::makeConstantsWithType(Type *T, std::vector<Constant *> &Cs) {
if (auto *IntTy = dyn_cast<IntegerType>(T)) {
uint64_t W = IntTy->getBitWidth();
+ Cs.push_back(ConstantInt::get(IntTy, 0));
+ Cs.push_back(ConstantInt::get(IntTy, 1));
+ Cs.push_back(ConstantInt::get(IntTy, 42));
Cs.push_back(ConstantInt::get(IntTy, APInt::getMaxValue(W)));
Cs.push_back(ConstantInt::get(IntTy, APInt::getMinValue(W)));
Cs.push_back(ConstantInt::get(IntTy, APInt::getSignedMaxValue(W)));
@@ -24,10 +27,24 @@ void fuzzerop::makeConstantsWithType(Type *T, std::vector<Constant *> &Cs) {
auto &Ctx = T->getContext();
auto &Sem = T->getFltSemantics();
Cs.push_back(ConstantFP::get(Ctx, APFloat::getZero(Sem)));
+ Cs.push_back(ConstantFP::get(Ctx, APFloat(Sem, 1)));
+ Cs.push_back(ConstantFP::get(Ctx, APFloat(Sem, 42)));
Cs.push_back(ConstantFP::get(Ctx, APFloat::getLargest(Sem)));
Cs.push_back(ConstantFP::get(Ctx, APFloat::getSmallest(Sem)));
- } else
+ Cs.push_back(ConstantFP::get(Ctx, APFloat::getInf(Sem)));
+ Cs.push_back(ConstantFP::get(Ctx, APFloat::getNaN(Sem)));
+ } else if (VectorType *VecTy = dyn_cast<VectorType>(T)) {
+ std::vector<Constant *> EleCs;
+ Type *EltTy = VecTy->getElementType();
+ makeConstantsWithType(EltTy, EleCs);
+ ElementCount EC = VecTy->getElementCount();
+ for (Constant *Elt : EleCs) {
+ Cs.push_back(ConstantVector::getSplat(EC, Elt));
+ }
+ } else {
Cs.push_back(UndefValue::get(T));
+ Cs.push_back(PoisonValue::get(T));
+ }
}
std::vector<Constant *> fuzzerop::makeConstantsWithType(Type *T) {
diff --git a/llvm/lib/FuzzMutate/Operations.cpp b/llvm/lib/FuzzMutate/Operations.cpp
index 46ebbef4d9d24..48455c781629f 100644
--- a/llvm/lib/FuzzMutate/Operations.cpp
+++ b/llvm/lib/FuzzMutate/Operations.cpp
@@ -67,11 +67,20 @@ void llvm::describeFuzzerFloatOps(std::vector<fuzzerop::OpDescriptor> &Ops) {
Ops.push_back(cmpOpDescriptor(1, Instruction::FCmp, CmpInst::FCMP_TRUE));
}
+void llvm::describeFuzzerUnaryOperations(
+ std::vector<fuzzerop::OpDescriptor> &Ops) {
+ Ops.push_back(fnegDescriptor(1));
+}
+
void llvm::describeFuzzerControlFlowOps(
std::vector<fuzzerop::OpDescriptor> &Ops) {
Ops.push_back(splitBlockDescriptor(1));
}
+void llvm::describeFuzzerOtherOps(std::vector<fuzzerop::OpDescriptor> &Ops) {
+ Ops.push_back(selectDescriptor(1));
+}
+
void llvm::describeFuzzerPointerOps(std::vector<fuzzerop::OpDescriptor> &Ops) {
Ops.push_back(gepDescriptor(1));
}
@@ -88,6 +97,22 @@ void llvm::describeFuzzerVectorOps(std::vector<fuzzerop::OpDescriptor> &Ops) {
Ops.push_back(shuffleVectorDescriptor(1));
}
+OpDescriptor llvm::fuzzerop::selectDescriptor(unsigned Weight) {
+ auto buildOp = [](ArrayRef<Value *> Srcs, Instruction *Inst) {
+ return SelectInst::Create(Srcs[0], Srcs[1], Srcs[2], "S", Inst);
+ };
+ return {Weight,
+ {boolOrVecBoolType(), matchFirstLengthWAnyType(), matchSecondType()},
+ buildOp};
+}
+
+OpDescriptor llvm::fuzzerop::fnegDescriptor(unsigned Weight) {
+ auto buildOp = [](ArrayRef<Value *> Srcs, Instruction *Inst) {
+ return UnaryOperator::Create(Instruction::FNeg, Srcs[0], "F", Inst);
+ };
+ return {Weight, {anyFloatOrVecFloatType()}, buildOp};
+}
+
OpDescriptor llvm::fuzzerop::binOpDescriptor(unsigned Weight,
Instruction::BinaryOps Op) {
auto buildOp = [Op](ArrayRef<Value *> Srcs, Instruction *Inst) {
@@ -107,13 +132,13 @@ OpDescriptor llvm::fuzzerop::binOpDescriptor(unsigned Weight,
case Instruction::And:
case Instruction::Or:
case Instruction::Xor:
- return {Weight, {anyIntType(), matchFirstType()}, buildOp};
+ return {Weight, {anyIntOrVecIntType(), matchFirstType()}, buildOp};
case Instruction::FAdd:
case Instruction::FSub:
case Instruction::FMul:
case Instruction::FDiv:
case Instruction::FRem:
- return {Weight, {anyFloatType(), matchFirstType()}, buildOp};
+ return {Weight, {anyFloatOrVecFloatType(), matchFirstType()}, buildOp};
case Instruction::BinaryOpsEnd:
llvm_unreachable("Value out of range of enum");
}
@@ -129,9 +154,9 @@ OpDescriptor llvm::fuzzerop::cmpOpDescriptor(unsigned Weight,
switch (CmpOp) {
case Instruction::ICmp:
- return {Weight, {anyIntType(), matchFirstType()}, buildOp};
+ return {Weight, {anyIntOrVecIntType(), matchFirstType()}, buildOp};
case Instruction::FCmp:
- return {Weight, {anyFloatType(), matchFirstType()}, buildOp};
+ return {Weight, {anyFloatOrVecFloatType(), matchFirstType()}, buildOp};
default:
llvm_unreachable("CmpOp must be ICmp or FCmp");
}
diff --git a/llvm/unittests/FuzzMutate/OperationsTest.cpp b/llvm/unittests/FuzzMutate/OperationsTest.cpp
index d4c589d74b031..82a37e02aab8c 100644
--- a/llvm/unittests/FuzzMutate/OperationsTest.cpp
+++ b/llvm/unittests/FuzzMutate/OperationsTest.cpp
@@ -91,10 +91,17 @@ TEST(OperationsTest, SourcePreds) {
Constant *s = ConstantStruct::get(StructType::create(Ctx, "OpaqueStruct"));
Constant *a =
ConstantArray::get(ArrayType::get(i32->getType(), 2), {i32, i32});
+ Constant *v8i1 = ConstantVector::getSplat(ElementCount::getFixed(8), i1);
Constant *v8i8 = ConstantVector::getSplat(ElementCount::getFixed(8), i8);
Constant *v4f16 = ConstantVector::getSplat(ElementCount::getFixed(4), f16);
Constant *p0i32 =
ConstantPointerNull::get(PointerType::get(i32->getType(), 0));
+ Constant *v8p0i32 =
+ ConstantVector::getSplat(ElementCount::getFixed(8), p0i32);
+ Constant *vni32 = ConstantVector::getSplat(ElementCount::getScalable(8), i32);
+ Constant *vnf64 = ConstantVector::getSplat(ElementCount::getScalable(8), f64);
+ Constant *vnp0i32 =
+ ConstantVector::getSplat(ElementCount::getScalable(8), p0i32);
auto OnlyI32 = onlyType(i32->getType());
EXPECT_TRUE(OnlyI32.matches({}, i32));
@@ -126,6 +133,36 @@ TEST(OperationsTest, SourcePreds) {
AnyInt.generate({}, {i32->getType(), f16->getType(), v8i8->getType()}),
AllOf(SizeIs(Ge(1u)), Each(TypesMatch(i32))));
+ auto AnyIntOrVecInt = anyIntOrVecIntType();
+ EXPECT_TRUE(AnyIntOrVecInt.matches({}, i1));
+ EXPECT_TRUE(AnyIntOrVecInt.matches({}, i64));
+ EXPECT_FALSE(AnyIntOrVecInt.matches({}, f32));
+ EXPECT_FALSE(AnyIntOrVecInt.matches({}, v4f16));
+ EXPECT_TRUE(AnyIntOrVecInt.matches({}, v8i8));
+ EXPECT_FALSE(AnyIntOrVecInt.matches({}, v4f16));
+ EXPECT_FALSE(AnyIntOrVecInt.matches({}, v8p0i32));
+ EXPECT_TRUE(AnyIntOrVecInt.matches({}, vni32));
+ EXPECT_FALSE(AnyIntOrVecInt.matches({}, vnf64));
+ EXPECT_FALSE(AnyIntOrVecInt.matches({}, vnp0i32));
+
+ EXPECT_THAT(AnyIntOrVecInt.generate({}, {v8i8->getType()}),
+ AllOf(Each(TypesMatch(v8i8))));
+
+ auto BoolOrVecBool = boolOrVecBoolType();
+ EXPECT_TRUE(BoolOrVecBool.matches({}, i1));
+ EXPECT_FALSE(BoolOrVecBool.matches({}, i64));
+ EXPECT_FALSE(BoolOrVecBool.matches({}, f32));
+ EXPECT_FALSE(BoolOrVecBool.matches({}, v4f16));
+ EXPECT_TRUE(BoolOrVecBool.matches({}, v8i1));
+ EXPECT_FALSE(BoolOrVecBool.matches({}, v4f16));
+ EXPECT_FALSE(BoolOrVecBool.matches({}, v8p0i32));
+ EXPECT_FALSE(BoolOrVecBool.matches({}, vni32));
+ EXPECT_FALSE(BoolOrVecBool.matches({}, vnf64));
+ EXPECT_FALSE(BoolOrVecBool.matches({}, vnp0i32));
+
+ EXPECT_THAT(BoolOrVecBool.generate({}, {v8i8->getType(), v8i1->getType()}),
+ AllOf(Each(TypesMatch(v8i1))));
+
auto AnyFP = anyFloatType();
EXPECT_TRUE(AnyFP.matches({}, f16));
EXPECT_TRUE(AnyFP.matches({}, f32));
@@ -137,11 +174,30 @@ TEST(OperationsTest, SourcePreds) {
AnyFP.generate({}, {i32->getType(), f16->getType(), v8i8->getType()}),
AllOf(SizeIs(Ge(1u)), Each(TypesMatch(f16))));
+ auto AnyFPOrVecFP = anyFloatOrVecFloatType();
+ EXPECT_TRUE(AnyFPOrVecFP.matches({}, f16));
+ EXPECT_TRUE(AnyFPOrVecFP.matches({}, f32));
+ EXPECT_FALSE(AnyFPOrVecFP.matches({}, i16));
+ EXPECT_FALSE(AnyFPOrVecFP.matches({}, p0i32));
+ EXPECT_TRUE(AnyFPOrVecFP.matches({}, v4f16));
+ EXPECT_FALSE(AnyFPOrVecFP.matches({}, v8p0i32));
+ EXPECT_FALSE(AnyFPOrVecFP.matches({}, vni32));
+ EXPECT_TRUE(AnyFPOrVecFP.matches({}, vnf64));
+ EXPECT_FALSE(AnyFPOrVecFP.matches({}, vnp0i32));
+
+ EXPECT_THAT(AnyFPOrVecFP.generate(
+ {}, {i32->getType(), f16->getType(), v8i8->getType()}),
+ AllOf(SizeIs(Ge(1u)), Each(TypesMatch(f16))));
+ EXPECT_THAT(AnyFPOrVecFP.generate({}, {v4f16->getType()}),
+ AllOf(SizeIs(Ge(1u)), Each(TypesMatch(v4f16))));
+
auto AnyPtr = anyPtrType();
EXPECT_TRUE(AnyPtr.matches({}, p0i32));
EXPECT_FALSE(AnyPtr.matches({}, i8));
EXPECT_FALSE(AnyPtr.matches({}, a));
EXPECT_FALSE(AnyPtr.matches({}, v8i8));
+ EXPECT_FALSE(AnyPtr.matches({}, v8p0i32));
+ EXPECT_FALSE(AnyPtr.matches({}, vni32));
auto isPointer = [](Value *V) { return V->getType()->isPointerTy(); };
EXPECT_THAT(
@@ -154,9 +210,12 @@ TEST(OperationsTest, SourcePreds) {
EXPECT_FALSE(AnyVec.matches({}, i8));
EXPECT_FALSE(AnyVec.matches({}, a));
EXPECT_FALSE(AnyVec.matches({}, s));
+ EXPECT_TRUE(AnyVec.matches({}, v8p0i32));
+ EXPECT_TRUE(AnyVec.matches({}, vni32));
+ EXPECT_TRUE(AnyVec.matches({}, vnf64));
+ EXPECT_TRUE(AnyVec.matches({}, vnp0i32));
- EXPECT_THAT(AnyVec.generate({}, {v8i8->getType()}),
- ElementsAre(TypesMatch(v8i8)));
+ EXPECT_THAT(AnyVec.generate({}, {v8i8->getType()}), Each(TypesMatch(v8i8)));
auto First = matchFirstType();
EXPECT_TRUE(First.matches({i8}, i8));
@@ -167,6 +226,28 @@ TEST(OperationsTest, SourcePreds) {
EXPECT_THAT(First.generate({i8}, {}), Each(TypesMatch(i8)));
EXPECT_THAT(First.generate({f16}, {i8->getType()}), Each(TypesMatch(f16)));
EXPECT_THAT(First.generate({v8i8, i32}, {}), Each(TypesMatch(v8i8)));
+
+ auto FirstLength = matchFirstLengthWAnyType();
+ EXPECT_TRUE(FirstLength.matches({v8i8}, v8i1));
+
+ EXPECT_THAT(FirstLength.generate({v8i1}, {i8->getType()}),
+ Each(TypesMatch(v8i8)));
+
+ auto Second = matchSecondType();
+ EXPECT_TRUE(Second.matches({i32, i8}, i8));
+ EXPECT_TRUE(Second.matches({i8, f16}, f16));
+
+ EXPECT_THAT(Second.generate({v8i8, i32}, {}), Each(TypesMatch(i32)));
+ EXPECT_THAT(Second.generate({f32, f16}, {f16->getType()}),
+ Each(TypesMatch(f16)));
+
+ auto FirstScalar = matchScalarOfFirstType();
+ EXPECT_TRUE(FirstScalar.matches({v8i8}, i8));
+ EXPECT_TRUE(FirstScalar.matches({i8}, i8));
+ EXPECT_TRUE(FirstScalar.matches({v4f16}, f16));
+
+ EXPECT_THAT(FirstScalar.generate({v8i8}, {i8->getType()}),
+ Each(TypesMatch(i8)));
}
TEST(OperationsTest, SplitBlock) {
@@ -301,13 +382,12 @@ TEST(OperationsTest, GEPPointerOperand) {
// Check that we only pick sized pointers for the GEP instructions
LLVMContext Ctx;
- const char *SourceCode =
- "%opaque = type opaque\n"
- "declare void @f()\n"
- "define void @test(%opaque %o) {\n"
- " %a = alloca i64, i32 10\n"
- " ret void\n"
- "}";
+ const char *SourceCode = "%opaque = type opaque\n"
+ "declare void @f()\n"
+ "define void @test(%opaque %o) {\n"
+ " %a = alloca i64, i32 10\n"
+ " ret void\n"
+ "}";
auto M = parseAssembly(SourceCode, Ctx);
fuzzerop::OpDescriptor Descr = fuzzerop::gepDescriptor(1);
diff --git a/llvm/unittests/FuzzMutate/StrategiesTest.cpp b/llvm/unittests/FuzzMutate/StrategiesTest.cpp
index 688280f70f22b..92d7fc112020e 100644
--- a/llvm/unittests/FuzzMutate/StrategiesTest.cpp
+++ b/llvm/unittests/FuzzMutate/StrategiesTest.cpp
@@ -34,6 +34,17 @@ std::unique_ptr<IRMutator> createInjectorMutator() {
Type::getInt1Ty, Type::getInt8Ty, Type::getInt16Ty, Type::getInt32Ty,
Type::getInt64Ty, Type::getFloatTy, Type::getDoubleTy};
+ // Add vector 1, 2, 3, 4, and 8.
+ int VectorLength[] = {1, 2, 3, 4, 8};
+ std::vector<TypeGetter> BasicTypeGetters(Types);
+ for (auto typeGetter : BasicTypeGetters) {
+ for (int length : VectorLength) {
+ Types.push_back([typeGetter, length](LLVMContext &C) {
+ return VectorType::get(typeGetter(C), length, false);
+ });
+ }
+ }
+
std::vector<std::unique_ptr<IRMutationStrategy>> Strategies;
Strategies.push_back(std::make_unique<InjectorIRStrategy>(
InjectorIRStrategy::getDefaultOps()));
@@ -78,6 +89,25 @@ void IterateOnSource(StringRef Source, IRMutator &Mutator) {
}
}
+static void mutateAndVerifyModule(StringRef Source,
+ std::unique_ptr<IRMutator> &Mutator,
+ int repeat = 100) {
+ LLVMContext Ctx;
+ auto M = parseAssembly(Source.data(), Ctx);
+ std::mt19937 mt(Seed);
+ std::uniform_int_distribution<int> RandInt(INT_MIN, INT_MAX);
+ for (int i = 0; i < repeat; i++) {
+ Mutator->mutateModule(*M, RandInt(mt), Source.size(), Source.size() + 1024);
+ ASSERT_FALSE(verifyModule(*M, &errs()));
+ }
+}
+template <class Strategy>
+static void mutateAndVerifyModule(StringRef Source, int repeat = 100) {
+ auto Mutator = createMutator<Strategy>();
+ ASSERT_TRUE(Mutator);
+ mutateAndVerifyModule(Source, Mutator, repeat);
+}
+
TEST(InjectorIRStrategyTest, EmptyModule) {
// Test that we can inject into empty module
@@ -92,6 +122,13 @@ TEST(InjectorIRStrategyTest, EmptyModule) {
EXPECT_TRUE(!verifyModule(*M, &errs()));
}
+TEST(InjectorIRStrategyTest, LargeInsertion) {
+ StringRef Source = "";
+ auto Mutator = createInjectorMutator();
+ ASSERT_TRUE(Mutator);
+ mutateAndVerifyModule(Source, Mutator, 100);
+}
+
TEST(InstDeleterIRStrategyTest, EmptyFunction) {
// Test that we don't crash even if we can't remove from one of the functions.
@@ -385,21 +422,6 @@ TEST(InstModificationIRStrategy, FastMath) {
ASSERT_TRUE(p.second);
}
-template <class Strategy>
-static void mutateAndVerifyModule(StringRef Source, int repeat = 100) {
- LLVMContext Ctx;
- auto Mutator = createMutator<Strategy>();
- ASSERT_TRUE(Mutator);
-
- auto M = parseAssembly(Source.data(), Ctx);
- std::mt19937 mt(Seed);
- std::uniform_int_distribution<int> RandInt(INT_MIN, INT_MAX);
- for (int i = 0; i < repeat; i++) {
- Mutator->mutateModule(*M, RandInt(mt), Source.size(), Source.size() + 1024);
- ASSERT_FALSE(verifyModule(*M, &errs()));
- }
-}
-
TEST(InsertCFGStrategy, CFG) {
StringRef Source = "\n\
define i32 @test(i1 %C1, i1 %C2, i1 %C3, i16 %S1, i16 %S2, i32 %I1) { \n\
More information about the llvm-commits
mailing list