blob: 4960b8205de5cde957858d47a8d9f9448cf5b1e2 [file] [log] [blame]
Chris Lattner4a106452002-12-23 23:50:16 +00001//===- Miscompilation.cpp - Debug program miscompilations -----------------===//
2//
3// This file implements program miscompilation debugging support.
4//
5//===----------------------------------------------------------------------===//
6
7#include "BugDriver.h"
8#include "SystemUtils.h"
9#include "llvm/Pass.h"
10#include "llvm/Module.h"
Chris Lattner640f22e2003-04-24 17:02:17 +000011#include "llvm/Transforms/Utils/Cloning.h"
12#include "llvm/Transforms/Utils/Linker.h"
Chris Lattner4a106452002-12-23 23:50:16 +000013#include "Support/CommandLine.h"
14
15// Anonymous namespace to define command line options for miscompilation
16// debugging.
17//
18namespace {
19 // Output - The user can specify a file containing the expected output of the
20 // program. If this filename is set, it is used as the reference diff source,
21 // otherwise the raw input run through an interpreter is used as the reference
22 // source.
23 //
24 cl::opt<std::string>
25 Output("output", cl::desc("Specify a reference program output "
26 "(for miscompilation detection)"));
27}
28
Chris Lattner640f22e2003-04-24 17:02:17 +000029template<typename ElTy>
30struct ListReducer {
31 enum TestResult {
32 NoFailure, // No failure of the predicate was detected
33 KeepSuffix, // The suffix alone satisfies the predicate
34 KeepPrefix, // The prefix alone satisfies the predicate
35 };
36
37 // doTest - This virtual function should be overriden by subclasses to
38 // implement the test desired. The testcase is only required to test to see
39 // if the Kept list still satisfies the property, but if it is going to check
40 // the prefix anyway, it can.
41 //
42 virtual TestResult doTest(const std::vector<ElTy> &Prefix,
43 const std::vector<ElTy> &Kept) = 0;
44
45 // reduceList - This function attempts to reduce the length of the specified
46 // list while still maintaining the "test" property. This is the core of the
47 // "work" that bugpoint does.
48 //
49 void reduceList(std::vector<ElTy> &TheList) {
50 unsigned MidTop = TheList.size();
51 while (MidTop > 1) {
52 unsigned Mid = MidTop / 2;
53 std::vector<ElTy> Prefix(TheList.begin()+Mid, TheList.end());
54 std::vector<ElTy> Kept (TheList.begin(), TheList.begin()+Mid);
55
56 switch (doTest(Prefix, Kept)) {
57 case KeepSuffix:
58 // The property still holds. We can just drop the prefix elements, and
59 // shorten the list to the "kept" elements.
60 TheList.swap(Kept);
61 MidTop = TheList.size();
62 break;
63 case KeepPrefix:
64 // The predicate still holds, shorten the list to the prefix elements.
65 TheList.swap(Prefix);
66 MidTop = TheList.size();
67 break;
68 case NoFailure:
69 // Otherwise the property doesn't hold. Some of the elements we removed
70 // must be neccesary to maintain the property.
71 MidTop = Mid;
72 break;
73 }
74 }
Chris Lattnera148ccb2003-04-24 19:32:42 +000075
76 // Okay, we trimmed as much off the top and the bottom of the list as we
77 // could. If there is more two elements in the list, try deleting interior
78 // elements and testing that.
79 //
80 if (TheList.size() > 2) {
81 bool Changed = true;
82 std::vector<ElTy> EmptyList;
83 while (Changed) {
84 Changed = false;
85 std::vector<ElTy> TrimmedList;
86 for (unsigned i = 1; i < TheList.size()-1; ++i) { // Check interior elts
87 std::vector<ElTy> TestList(TheList);
88 TestList.erase(TestList.begin()+i);
89
90 if (doTest(EmptyList, TestList) == KeepSuffix) {
91 // We can trim down the list!
92 TheList.swap(TestList);
93 --i; // Don't skip an element of the list
94 Changed = true;
95 }
96 }
97 }
98 }
Chris Lattner640f22e2003-04-24 17:02:17 +000099 }
100};
101
102class ReduceMiscompilingPasses : public ListReducer<const PassInfo*> {
103 BugDriver &BD;
104public:
105 ReduceMiscompilingPasses(BugDriver &bd) : BD(bd) {}
106
107 virtual TestResult doTest(const std::vector<const PassInfo*> &Prefix,
108 const std::vector<const PassInfo*> &Kept);
109};
110
111ReduceMiscompilingPasses::TestResult
112ReduceMiscompilingPasses::doTest(const std::vector<const PassInfo*> &Prefix,
113 const std::vector<const PassInfo*> &Kept) {
114 // First, run the program with just the Kept passes. If it is still broken
115 // with JUST the kept passes, discard the prefix passes.
116 std::cout << "Checking to see if '" << getPassesString(Kept)
117 << "' compile correctly: ";
118
119 std::string BytecodeResult;
120 if (BD.runPasses(Kept, BytecodeResult, false/*delete*/, true/*quiet*/)) {
121 std::cerr << BD.getToolName() << ": Error running this sequence of passes"
122 << " on the input program!\n";
123 exit(1);
124 }
125
126 // Check to see if the finished program matches the reference output...
127 if (BD.diffProgram(Output, BytecodeResult, true /*delete bytecode*/)) {
128 std::cout << "nope.\n";
129 return KeepSuffix; // Miscompilation detected!
130 }
131 std::cout << "yup.\n"; // No miscompilation!
132
133 if (Prefix.empty()) return NoFailure;
134
135 // First, run the program with just the Kept passes. If it is still broken
136 // with JUST the kept passes, discard the prefix passes.
137 std::cout << "Checking to see if '" << getPassesString(Prefix)
138 << "' compile correctly: ";
139
140 // If it is not broken with the kept passes, it's possible that the prefix
141 // passes must be run before the kept passes to break it. If the program
142 // WORKS after the prefix passes, but then fails if running the prefix AND
143 // kept passes, we can update our bytecode file to include the result of the
144 // prefix passes, then discard the prefix passes.
145 //
146 if (BD.runPasses(Prefix, BytecodeResult, false/*delete*/, true/*quiet*/)) {
147 std::cerr << BD.getToolName() << ": Error running this sequence of passes"
148 << " on the input program!\n";
149 exit(1);
150 }
151
152 // If the prefix maintains the predicate by itself, only keep the prefix!
153 if (BD.diffProgram(Output, BytecodeResult)) {
154 std::cout << "nope.\n";
155 removeFile(BytecodeResult);
156 return KeepPrefix;
157 }
158 std::cout << "yup.\n"; // No miscompilation!
159
160 // Ok, so now we know that the prefix passes work, try running the suffix
161 // passes on the result of the prefix passes.
162 //
163 Module *PrefixOutput = BD.ParseInputFile(BytecodeResult);
164 if (PrefixOutput == 0) {
165 std::cerr << BD.getToolName() << ": Error reading bytecode file '"
166 << BytecodeResult << "'!\n";
167 exit(1);
168 }
169 removeFile(BytecodeResult); // No longer need the file on disk
170
171 std::cout << "Checking to see if '" << getPassesString(Kept)
172 << "' passes compile correctly after the '"
173 << getPassesString(Prefix) << "' passes: ";
174
175 Module *OriginalInput = BD.Program;
176 BD.Program = PrefixOutput;
177 if (BD.runPasses(Kept, BytecodeResult, false/*delete*/, true/*quiet*/)) {
178 std::cerr << BD.getToolName() << ": Error running this sequence of passes"
179 << " on the input program!\n";
180 exit(1);
181 }
182
183 // Run the result...
184 if (BD.diffProgram(Output, BytecodeResult, true/*delete bytecode*/)) {
185 std::cout << "nope.\n";
186 delete OriginalInput; // We pruned down the original input...
187 return KeepPrefix;
188 }
189
190 // Otherwise, we must not be running the bad pass anymore.
191 std::cout << "yup.\n"; // No miscompilation!
192 BD.Program = OriginalInput; // Restore original program
193 delete PrefixOutput; // Free experiment
194 return NoFailure;
195}
196
197static void PrintFunctionList(const std::vector<Function*> &Funcs) {
198 for (unsigned i = 0, e = Funcs.size(); i != e; ++i) {
199 if (i) std::cout << ", ";
200 std::cout << Funcs[i]->getName();
201 }
202}
203
204
205class ReduceMiscompilingFunctions : public ListReducer<Function*> {
206 BugDriver &BD;
207public:
208 ReduceMiscompilingFunctions(BugDriver &bd) : BD(bd) {}
209
210 virtual TestResult doTest(const std::vector<Function*> &Prefix,
211 const std::vector<Function*> &Kept) {
212 if (TestFuncs(Kept, false))
213 return KeepSuffix;
Chris Lattnera148ccb2003-04-24 19:32:42 +0000214 if (!Prefix.empty() && TestFuncs(Prefix, false))
Chris Lattner640f22e2003-04-24 17:02:17 +0000215 return KeepPrefix;
216 return NoFailure;
217 }
218
219 bool TestFuncs(const std::vector<Function*> &Prefix, bool EmitBytecode);
220};
221
222// DeleteFunctionBody - "Remove" the function by deleting all of it's basic
223// blocks, making it external.
224//
225static void DeleteFunctionBody(Function *F) {
226 // First, break circular use/def chain references...
227 for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I)
228 I->dropAllReferences();
229
230 // Next, delete all of the basic blocks.
231 F->getBasicBlockList().clear();
232
233 assert(F->isExternal() && "This didn't make the function external!");
234}
235
236
237bool ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function*> &Funcs,
238 bool EmitBytecode) {
239 // Test to see if the function is misoptimized if we ONLY run it on the
240 // functions listed in Funcs.
241 if (!EmitBytecode) {
242 std::cout << "Checking to see if the program is misoptimized when these "
243 << "functions are run\nthrough the passes: ";
244 PrintFunctionList(Funcs);
245 std::cout << "\n";
246 } else {
247 std::cout <<"Outputting reduced bytecode files which expose the problem:\n";
248 }
249
250 // First step: clone the module for the two halves of the program we want.
251 Module *ToOptimize = CloneModule(BD.Program);
252
253 // Second step: Make sure functions & globals are all external so that linkage
254 // between the two modules will work.
255 for (Module::iterator I = ToOptimize->begin(), E = ToOptimize->end();I!=E;++I)
256 I->setLinkage(GlobalValue::ExternalLinkage);
257 for (Module::giterator I = ToOptimize->gbegin(), E = ToOptimize->gend();
258 I != E; ++I)
259 I->setLinkage(GlobalValue::ExternalLinkage);
260
261 // Third step: make a clone of the externalized program for the non-optimized
262 // part.
263 Module *ToNotOptimize = CloneModule(ToOptimize);
264
265 // Fourth step: Remove the test functions from the ToNotOptimize module, and
266 // all of the global variables.
267 for (unsigned i = 0, e = Funcs.size(); i != e; ++i) {
268 Function *TNOF = ToNotOptimize->getFunction(Funcs[i]->getName(),
269 Funcs[i]->getFunctionType());
270 assert(TNOF && "Function doesn't exist in module!");
271 DeleteFunctionBody(TNOF); // Function is now external in this module!
272 }
273 for (Module::giterator I = ToNotOptimize->gbegin(), E = ToNotOptimize->gend();
274 I != E; ++I)
275 I->setInitializer(0); // Delete the initializer to make it external
276
277 if (EmitBytecode) {
278 std::cout << " Non-optimized portion: ";
279 std::swap(BD.Program, ToNotOptimize);
280 BD.EmitProgressBytecode("tonotoptimize", true);
281 std::swap(BD.Program, ToNotOptimize);
282 }
283
284 // Fifth step: Remove all functions from the ToOptimize module EXCEPT for the
285 // ones specified in Funcs. We know which ones these are because they are
286 // non-external in ToOptimize, but external in ToNotOptimize.
287 //
288 for (Module::iterator I = ToOptimize->begin(), E = ToOptimize->end();I!=E;++I)
289 if (!I->isExternal()) {
290 Function *TNOF = ToNotOptimize->getFunction(I->getName(),
291 I->getFunctionType());
292 assert(TNOF && "Function doesn't exist in ToNotOptimize module??");
293 if (!TNOF->isExternal())
294 DeleteFunctionBody(I);
295 }
296
297 if (EmitBytecode) {
298 std::cout << " Portion that is input to optimizer: ";
299 std::swap(BD.Program, ToOptimize);
300 BD.EmitProgressBytecode("tooptimize");
301 std::swap(BD.Program, ToOptimize);
302 }
303
304 // Sixth step: Run the optimization passes on ToOptimize, producing a
305 // transformed version of the functions being tested.
306 Module *OldProgram = BD.Program;
307 BD.Program = ToOptimize;
308
309 if (!EmitBytecode)
310 std::cout << " Optimizing functions being tested: ";
311 std::string BytecodeResult;
312 if (BD.runPasses(BD.PassesToRun, BytecodeResult, false/*delete*/,
313 true/*quiet*/)) {
314 std::cerr << BD.getToolName() << ": Error running this sequence of passes"
315 << " on the input program!\n";
316 exit(1);
317 }
318
319 if (!EmitBytecode)
320 std::cout << "done.\n";
321
322 delete BD.Program; // Delete the old "ToOptimize" module
323 BD.Program = BD.ParseInputFile(BytecodeResult);
324
325 if (EmitBytecode) {
326 std::cout << " 'tooptimize' after being optimized: ";
327 BD.EmitProgressBytecode("optimized", true);
328 }
329
330 if (BD.Program == 0) {
331 std::cerr << BD.getToolName() << ": Error reading bytecode file '"
332 << BytecodeResult << "'!\n";
333 exit(1);
334 }
335 removeFile(BytecodeResult); // No longer need the file on disk
336
337 // Seventh step: Link the optimized part of the program back to the
338 // unoptimized part of the program.
339 //
340 if (LinkModules(BD.Program, ToNotOptimize, &BytecodeResult)) {
341 std::cerr << BD.getToolName() << ": Error linking modules together:"
342 << BytecodeResult << "\n";
343 exit(1);
344 }
345 delete ToNotOptimize; // We are done with this module...
346
347 if (EmitBytecode) {
348 std::cout << " Program as tested: ";
349 BD.EmitProgressBytecode("linked", true);
350 delete BD.Program;
351 BD.Program = OldProgram;
352 return false; // We don't need to actually execute the program here.
353 }
354
355 std::cout << " Checking to see if the merged program executes correctly: ";
356
357 // Eighth step: Execute the program. If it does not match the expected
358 // output, then 'Funcs' are being misoptimized!
359 bool Broken = BD.diffProgram(Output);
360
361 delete BD.Program; // Delete the hacked up program
362 BD.Program = OldProgram; // Restore the original
363
364 std::cout << (Broken ? "nope.\n" : "yup.\n");
365 return Broken;
366}
367
368
Chris Lattner4a106452002-12-23 23:50:16 +0000369/// debugMiscompilation - This method is used when the passes selected are not
370/// crashing, but the generated output is semantically different from the
371/// input.
372///
373bool BugDriver::debugMiscompilation() {
374 std::cout << "*** Debugging miscompilation!\n";
375
376 // Set up the execution environment, selecting a method to run LLVM bytecode.
377 if (initializeExecutionEnvironment()) return true;
378
379 // Run the raw input to see where we are coming from. If a reference output
380 // was specified, make sure that the raw output matches it. If not, it's a
381 // problem in the front-end or whatever produced the input code.
382 //
383 bool CreatedOutput = false;
384 if (Output.empty()) {
385 std::cout << "Generating reference output from raw program...";
386 Output = executeProgram("bugpoint.reference.out");
387 CreatedOutput = true;
Chris Lattnereea21dd2003-04-23 20:41:18 +0000388 std::cout << " done! Reference output is: bugpoint.reference.out.\n";
Chris Lattner4a106452002-12-23 23:50:16 +0000389 } else if (diffProgram(Output)) {
390 std::cout << "\n*** Input program does not match reference diff!\n"
391 << " Must be problem with input source!\n";
392 return false; // Problem found
393 }
394
Chris Lattner640f22e2003-04-24 17:02:17 +0000395 // Figure out which transformations miscompile the input program.
396 unsigned OldSize = PassesToRun.size();
397 ReduceMiscompilingPasses(*this).reduceList(PassesToRun);
Chris Lattner4a106452002-12-23 23:50:16 +0000398
399 // Make sure something was miscompiled...
Chris Lattner640f22e2003-04-24 17:02:17 +0000400 if (PassesToRun.size() == OldSize) {
Chris Lattner4a106452002-12-23 23:50:16 +0000401 std::cerr << "*** Optimized program matches reference output! No problem "
402 << "detected...\nbugpoint can't help you with your problem!\n";
403 return false;
404 }
405
Chris Lattner640f22e2003-04-24 17:02:17 +0000406 std::cout << "\n*** Found miscompiling pass"
407 << (PassesToRun.size() == 1 ? "" : "es") << ": "
408 << getPassesString(PassesToRun) << "\n";
409 EmitProgressBytecode("passinput");
Chris Lattner4a106452002-12-23 23:50:16 +0000410
Chris Lattner640f22e2003-04-24 17:02:17 +0000411
412 // Okay, now that we have reduced the list of passes which are causing the
413 // failure, see if we can pin down which functions are being
414 // miscompiled... first build a list of all of the non-external functions in
415 // the program.
416 std::vector<Function*> MiscompiledFunctions;
417 for (Module::iterator I = Program->begin(), E = Program->end(); I != E; ++I)
418 if (!I->isExternal())
419 MiscompiledFunctions.push_back(I);
420
421 // Do the reduction...
422 ReduceMiscompilingFunctions(*this).reduceList(MiscompiledFunctions);
423
424 std::cout << "\n*** The following functions are being miscompiled: ";
425 PrintFunctionList(MiscompiledFunctions);
426 std::cout << "\n";
427
428 // Output a bunch of bytecode files for the user...
429 ReduceMiscompilingFunctions(*this).TestFuncs(MiscompiledFunctions, true);
Chris Lattner4a106452002-12-23 23:50:16 +0000430
431 if (CreatedOutput) removeFile(Output);
Chris Lattner4a106452002-12-23 23:50:16 +0000432 return false;
433}