@@ -314,6 +314,66 @@ bool ReduceCrashingFunctions::TestFuncs(std::vector<Function *> &Funcs) {
314
314
return false ;
315
315
}
316
316
317
+ namespace {
318
+ // / ReduceCrashingFunctionAttributes reducer - This works by removing
319
+ // / attributes on a particular function and seeing if the program still crashes.
320
+ // / If it does, then keep the newer, smaller program.
321
+ // /
322
+ class ReduceCrashingFunctionAttributes : public ListReducer <Attribute> {
323
+ BugDriver &BD;
324
+ std::string FnName;
325
+ BugTester TestFn;
326
+
327
+ public:
328
+ ReduceCrashingFunctionAttributes (BugDriver &bd, const std::string &FnName,
329
+ BugTester testFn)
330
+ : BD(bd), FnName(FnName), TestFn(testFn) {}
331
+
332
+ Expected<TestResult> doTest (std::vector<Attribute> &Prefix,
333
+ std::vector<Attribute> &Kept) override {
334
+ if (!Kept.empty () && TestFuncAttrs (Kept))
335
+ return KeepSuffix;
336
+ if (!Prefix.empty () && TestFuncAttrs (Prefix))
337
+ return KeepPrefix;
338
+ return NoFailure;
339
+ }
340
+
341
+ bool TestFuncAttrs (std::vector<Attribute> &Attrs);
342
+ };
343
+ }
344
+
345
+ bool ReduceCrashingFunctionAttributes::TestFuncAttrs (
346
+ std::vector<Attribute> &Attrs) {
347
+ // Clone the program to try hacking it apart...
348
+ std::unique_ptr<Module> M = CloneModule (BD.getProgram ());
349
+ Function *F = M->getFunction (FnName);
350
+
351
+ // Build up an AttributeList from the attributes we've been given by the
352
+ // reducer.
353
+ AttrBuilder AB;
354
+ for (auto A : Attrs)
355
+ AB.addAttribute (A);
356
+ AttributeList NewAttrs;
357
+ NewAttrs =
358
+ NewAttrs.addAttributes (BD.getContext (), AttributeList::FunctionIndex, AB);
359
+
360
+ // Set this new list of attributes on the function.
361
+ F->setAttributes (NewAttrs);
362
+
363
+ // Try running on the hacked up program...
364
+ if (TestFn (BD, M.get ())) {
365
+ BD.setNewProgram (std::move (M)); // It crashed, keep the trimmed version...
366
+
367
+ // Pass along the set of attributes that caused the crash.
368
+ Attrs.clear ();
369
+ for (Attribute A : NewAttrs.getFnAttributes ()) {
370
+ Attrs.push_back (A);
371
+ }
372
+ return true ;
373
+ }
374
+ return false ;
375
+ }
376
+
317
377
namespace {
318
378
// / Simplify the CFG without completely destroying it.
319
379
// / This is not well defined, but basically comes down to "try to eliminate
@@ -1056,6 +1116,38 @@ static Error DebugACrash(BugDriver &BD, BugTester TestFn) {
1056
1116
BD.EmitProgressBitcode (BD.getProgram (), " reduced-function" );
1057
1117
}
1058
1118
1119
+ // For each remaining function, try to reduce that function's attributes.
1120
+ std::vector<std::string> FunctionNames;
1121
+ for (Function &F : BD.getProgram ())
1122
+ FunctionNames.push_back (F.getName ());
1123
+
1124
+ if (!FunctionNames.empty () && !BugpointIsInterrupted) {
1125
+ outs () << " \n *** Attempting to reduce the number of function attributes in "
1126
+ " the testcase\n " ;
1127
+
1128
+ unsigned OldSize = 0 ;
1129
+ unsigned NewSize = 0 ;
1130
+ for (std::string &Name : FunctionNames) {
1131
+ Function *Fn = BD.getProgram ().getFunction (Name);
1132
+ assert (Fn && " Could not find funcion?" );
1133
+
1134
+ std::vector<Attribute> Attrs;
1135
+ for (Attribute A : Fn->getAttributes ().getFnAttributes ())
1136
+ Attrs.push_back (A);
1137
+
1138
+ OldSize += Attrs.size ();
1139
+ Expected<bool > Result =
1140
+ ReduceCrashingFunctionAttributes (BD, Name, TestFn).reduceList (Attrs);
1141
+ if (Error E = Result.takeError ())
1142
+ return E;
1143
+
1144
+ NewSize += Attrs.size ();
1145
+ }
1146
+
1147
+ if (OldSize < NewSize)
1148
+ BD.EmitProgressBitcode (BD.getProgram (), " reduced-function-attributes" );
1149
+ }
1150
+
1059
1151
// Attempt to change conditional branches into unconditional branches to
1060
1152
// eliminate blocks.
1061
1153
if (!DisableSimplifyCFG && !BugpointIsInterrupted) {
0 commit comments