@@ -37,24 +37,13 @@ std::unique_ptr<IRMutator> createInjectorMutator() {
37
37
return std::make_unique<IRMutator>(std::move (Types), std::move (Strategies));
38
38
}
39
39
40
- std::unique_ptr<IRMutator> createDeleterMutator () {
40
+ template < class Strategy > std::unique_ptr<IRMutator> createMutator () {
41
41
std::vector<TypeGetter> Types{
42
42
Type::getInt1Ty, Type::getInt8Ty, Type::getInt16Ty, Type::getInt32Ty,
43
43
Type::getInt64Ty, Type::getFloatTy, Type::getDoubleTy};
44
44
45
45
std::vector<std::unique_ptr<IRMutationStrategy>> Strategies;
46
- Strategies.push_back (std::make_unique<InstDeleterIRStrategy>());
47
-
48
- return std::make_unique<IRMutator>(std::move (Types), std::move (Strategies));
49
- }
50
-
51
- std::unique_ptr<IRMutator> createInstModifierMutator () {
52
- std::vector<TypeGetter> Types{
53
- Type::getInt1Ty, Type::getInt8Ty, Type::getInt16Ty, Type::getInt32Ty,
54
- Type::getInt64Ty, Type::getFloatTy, Type::getDoubleTy};
55
-
56
- std::vector<std::unique_ptr<IRMutationStrategy>> Strategies;
57
- Strategies.push_back (std::make_unique<InstModificationIRStrategy>());
46
+ Strategies.push_back (std::make_unique<Strategy>());
58
47
59
48
return std::make_unique<IRMutator>(std::move (Types), std::move (Strategies));
60
49
}
@@ -113,7 +102,7 @@ TEST(InstDeleterIRStrategyTest, EmptyFunction) {
113
102
" ret i32 %L6\n "
114
103
" }\n " ;
115
104
116
- auto Mutator = createDeleterMutator ();
105
+ auto Mutator = createMutator<InstDeleterIRStrategy> ();
117
106
ASSERT_TRUE (Mutator);
118
107
119
108
IterateOnSource (Source, *Mutator);
@@ -139,7 +128,7 @@ TEST(InstDeleterIRStrategyTest, PhiNodes) {
139
128
ret i32 %a.0\n \
140
129
}" ;
141
130
142
- auto Mutator = createDeleterMutator ();
131
+ auto Mutator = createMutator<InstDeleterIRStrategy> ();
143
132
ASSERT_TRUE (Mutator);
144
133
145
134
IterateOnSource (Source, *Mutator);
@@ -154,7 +143,7 @@ static void checkModifyNoUnsignedAndNoSignedWrap(StringRef Opc) {
154
143
ret i32 %a\n \
155
144
}" );
156
145
157
- auto Mutator = createInstModifierMutator ();
146
+ auto Mutator = createMutator<InstModificationIRStrategy> ();
158
147
ASSERT_TRUE (Mutator);
159
148
160
149
auto M = parseAssembly (Source.data (), Ctx);
@@ -198,7 +187,7 @@ TEST(InstModificationIRStrategyTest, ICmp) {
198
187
ret i1 %a\n \
199
188
}" ;
200
189
201
- auto Mutator = createInstModifierMutator ();
190
+ auto Mutator = createMutator<InstModificationIRStrategy> ();
202
191
ASSERT_TRUE (Mutator);
203
192
204
193
auto M = parseAssembly (Source.data (), Ctx);
@@ -223,7 +212,7 @@ TEST(InstModificationIRStrategyTest, GEP) {
223
212
ret i32* %gep\n \
224
213
}" ;
225
214
226
- auto Mutator = createInstModifierMutator ();
215
+ auto Mutator = createMutator<InstModificationIRStrategy> ();
227
216
ASSERT_TRUE (Mutator);
228
217
229
218
auto M = parseAssembly (Source.data (), Ctx);
@@ -239,4 +228,83 @@ TEST(InstModificationIRStrategyTest, GEP) {
239
228
240
229
EXPECT_TRUE (FoundInbounds);
241
230
}
231
+
232
+ // / The caller has to guarantee that function argument are used in the SAME
233
+ // / place as the operand.
234
+ void VerfyOperandShuffled (StringRef Source, std::pair<int , int > ShuffleItems) {
235
+ LLVMContext Ctx;
236
+ auto Mutator = createMutator<InstModificationIRStrategy>();
237
+ ASSERT_TRUE (Mutator);
238
+
239
+ auto M = parseAssembly (Source.data (), Ctx);
240
+ auto &F = *M->begin ();
241
+ Instruction *Inst = &*F.begin ()->begin ();
242
+ ASSERT_TRUE (M && !verifyModule (*M, &errs ()));
243
+ ASSERT_TRUE (Inst->getOperand (ShuffleItems.first ) ==
244
+ dyn_cast<Value>(F.getArg (ShuffleItems.first )));
245
+ ASSERT_TRUE (Inst->getOperand (ShuffleItems.second ) ==
246
+ dyn_cast<Value>(F.getArg (ShuffleItems.second )));
247
+
248
+ Mutator->mutateModule (*M, 0 , Source.size (), Source.size () + 100 );
249
+ EXPECT_TRUE (!verifyModule (*M, &errs ()));
250
+
251
+ EXPECT_TRUE (Inst->getOperand (ShuffleItems.first ) ==
252
+ dyn_cast<Value>(F.getArg (ShuffleItems.second )));
253
+ EXPECT_TRUE (Inst->getOperand (ShuffleItems.second ) ==
254
+ dyn_cast<Value>(F.getArg (ShuffleItems.first )));
255
+ }
256
+
257
+ TEST (InstModificationIRStrategyTest, ShuffleFAdd) {
258
+ StringRef Source = " \n \
259
+ define float @test(float %0, float %1) {\n \
260
+ %add = fadd float %0, %1\n \
261
+ ret float %add\n \
262
+ }" ;
263
+ VerfyOperandShuffled (Source, {0 , 1 });
264
+ }
265
+ TEST (InstModificationIRStrategyTest, ShuffleSelect) {
266
+ StringRef Source = " \n \
267
+ define float @test(i1 %0, float %1, float %2) {\n \
268
+ %select = select i1 %0, float %1, float %2\n \
269
+ ret float %select\n \
270
+ }" ;
271
+ VerfyOperandShuffled (Source, {1 , 2 });
272
+ }
273
+
274
+ void VerfyDivDidntShuffle (StringRef Source) {
275
+ LLVMContext Ctx;
276
+ auto Mutator = createMutator<InstModificationIRStrategy>();
277
+ ASSERT_TRUE (Mutator);
278
+
279
+ auto M = parseAssembly (Source.data (), Ctx);
280
+ auto &F = *M->begin ();
281
+ Instruction *Inst = &*F.begin ()->begin ();
282
+ ASSERT_TRUE (M && !verifyModule (*M, &errs ()));
283
+
284
+ EXPECT_TRUE (isa<Constant>(Inst->getOperand (0 )));
285
+ EXPECT_TRUE (Inst->getOperand (1 ) == dyn_cast<Value>(F.getArg (0 )));
286
+
287
+ Mutator->mutateModule (*M, Seed, Source.size (), Source.size () + 100 );
288
+ EXPECT_TRUE (!verifyModule (*M, &errs ()));
289
+
290
+ // Didn't shuffle.
291
+ EXPECT_TRUE (isa<Constant>(Inst->getOperand (0 )));
292
+ EXPECT_TRUE (Inst->getOperand (1 ) == dyn_cast<Value>(F.getArg (0 )));
293
+ }
294
+ TEST (InstModificationIRStrategyTest, DidntShuffleSDiv) {
295
+ StringRef Source = " \n \
296
+ define i32 @test(i32 %0) {\n \
297
+ %div = sdiv i32 0, %0\n \
298
+ ret i32 %div\n \
299
+ }" ;
300
+ VerfyDivDidntShuffle (Source);
301
+ }
302
+ TEST (InstModificationIRStrategyTest, DidntShuffleFRem) {
303
+ StringRef Source = " \n \
304
+ define <2 x double> @test(<2 x double> %0) {\n \
305
+ %div = frem <2 x double> <double 0.0, double 0.0>, %0\n \
306
+ ret <2 x double> %div\n \
307
+ }" ;
308
+ VerfyDivDidntShuffle (Source);
309
+ }
242
310
} // namespace
0 commit comments