@@ -49,6 +49,17 @@ std::unique_ptr<IRMutator> createDeleterMutator() {
49
49
return std::make_unique<IRMutator>(std::move (Types), std::move (Strategies));
50
50
}
51
51
52
+ std::unique_ptr<IRMutator> createInstModifierMutator () {
53
+ std::vector<TypeGetter> Types{
54
+ Type::getInt1Ty, Type::getInt8Ty, Type::getInt16Ty, Type::getInt32Ty,
55
+ Type::getInt64Ty, Type::getFloatTy, Type::getDoubleTy};
56
+
57
+ std::vector<std::unique_ptr<IRMutationStrategy>> Strategies;
58
+ Strategies.push_back (std::make_unique<InstModificationIRStrategy>());
59
+
60
+ return std::make_unique<IRMutator>(std::move (Types), std::move (Strategies));
61
+ }
62
+
52
63
std::unique_ptr<Module> parseAssembly (
53
64
const char *Assembly, LLVMContext &Context) {
54
65
@@ -135,4 +146,98 @@ TEST(InstDeleterIRStrategyTest, PhiNodes) {
135
146
IterateOnSource (Source, *Mutator);
136
147
}
137
148
149
+ static void checkModifyNoUnsignedAndNoSignedWrap (StringRef Opc) {
150
+ LLVMContext Ctx;
151
+ std::string Source = std::string (" \n \
152
+ define i32 @test(i32 %x) {\n \
153
+ %a = " ) + Opc.str () +
154
+ std::string (" i32 %x, 10\n \
155
+ ret i32 %a\n \
156
+ }" );
157
+
158
+ auto Mutator = createInstModifierMutator ();
159
+ ASSERT_TRUE (Mutator);
160
+
161
+ auto M = parseAssembly (Source.data (), Ctx);
162
+ auto &F = *M->begin ();
163
+ auto *AddI = &*F.begin ()->begin ();
164
+ ASSERT_TRUE (M && !verifyModule (*M, &errs ()));
165
+ bool FoundNUW = false ;
166
+ bool FoundNSW = false ;
167
+ for (int i = 0 ; i < 100 ; ++i) {
168
+ Mutator->mutateModule (*M, Seed + i, Source.size (), Source.size () + 100 );
169
+ EXPECT_TRUE (!verifyModule (*M, &errs ()));
170
+ FoundNUW |= AddI->hasNoUnsignedWrap ();
171
+ FoundNSW |= AddI->hasNoSignedWrap ();
172
+ }
173
+
174
+ // The mutator should have added nuw and nsw during some mutations.
175
+ EXPECT_TRUE (FoundNUW);
176
+ EXPECT_TRUE (FoundNSW);
177
+ }
178
+ TEST (InstModificationIRStrategyTest, Add) {
179
+ checkModifyNoUnsignedAndNoSignedWrap (" add" );
180
+ }
181
+
182
+ TEST (InstModificationIRStrategyTest, Sub) {
183
+ checkModifyNoUnsignedAndNoSignedWrap (" sub" );
184
+ }
185
+
186
+ TEST (InstModificationIRStrategyTest, Mul) {
187
+ checkModifyNoUnsignedAndNoSignedWrap (" mul" );
188
+ }
189
+
190
+ TEST (InstModificationIRStrategyTest, Shl) {
191
+ checkModifyNoUnsignedAndNoSignedWrap (" shl" );
192
+ }
193
+
194
+ TEST (InstModificationIRStrategyTest, ICmp) {
195
+ LLVMContext Ctx;
196
+ StringRef Source = " \n \
197
+ define i1 @test(i32 %x) {\n \
198
+ %a = icmp eq i32 %x, 10\n \
199
+ ret i1 %a\n \
200
+ }" ;
201
+
202
+ auto Mutator = createInstModifierMutator ();
203
+ ASSERT_TRUE (Mutator);
204
+
205
+ auto M = parseAssembly (Source.data (), Ctx);
206
+ auto &F = *M->begin ();
207
+ CmpInst *CI = cast<CmpInst>(&*F.begin ()->begin ());
208
+ ASSERT_TRUE (M && !verifyModule (*M, &errs ()));
209
+ bool FoundNE = false ;
210
+ for (int i = 0 ; i < 100 ; ++i) {
211
+ Mutator->mutateModule (*M, Seed + i, Source.size (), Source.size () + 100 );
212
+ EXPECT_TRUE (!verifyModule (*M, &errs ()));
213
+ FoundNE |= CI->getPredicate () == CmpInst::ICMP_NE;
214
+ }
215
+
216
+ EXPECT_TRUE (FoundNE);
217
+ }
218
+
219
+ TEST (InstModificationIRStrategyTest, GEP) {
220
+ LLVMContext Ctx;
221
+ StringRef Source = " \n \
222
+ define i32* @test(i32* %ptr) {\n \
223
+ %gep = getelementptr i32, i32* %ptr, i32 10\n \
224
+ ret i32* %gep\n \
225
+ }" ;
226
+
227
+ auto Mutator = createInstModifierMutator ();
228
+ ASSERT_TRUE (Mutator);
229
+
230
+ auto M = parseAssembly (Source.data (), Ctx);
231
+ auto &F = *M->begin ();
232
+ GetElementPtrInst *GEP = cast<GetElementPtrInst>(&*F.begin ()->begin ());
233
+ ASSERT_TRUE (M && !verifyModule (*M, &errs ()));
234
+ bool FoundInbounds = false ;
235
+ for (int i = 0 ; i < 100 ; ++i) {
236
+ Mutator->mutateModule (*M, Seed + i, Source.size (), Source.size () + 100 );
237
+ EXPECT_TRUE (!verifyModule (*M, &errs ()));
238
+ FoundInbounds |= GEP->isInBounds ();
239
+ }
240
+
241
+ EXPECT_TRUE (FoundInbounds);
242
+ }
138
243
}
0 commit comments