Miscompilation.cpp revision a64c3fa47e39f74c6e1f8d82249a719d6c696970
1//===- Miscompilation.cpp - Debug program miscompilations -----------------===// 2// 3// This file implements program miscompilation debugging support. 4// 5//===----------------------------------------------------------------------===// 6 7#include "BugDriver.h" 8#include "ListReducer.h" 9#include "llvm/Module.h" 10#include "llvm/Pass.h" 11#include "llvm/Transforms/Utils/Cloning.h" 12#include "llvm/Transforms/Utils/Linker.h" 13#include "Support/FileUtilities.h" 14 15class ReduceMiscompilingPasses : public ListReducer<const PassInfo*> { 16 BugDriver &BD; 17public: 18 ReduceMiscompilingPasses(BugDriver &bd) : BD(bd) {} 19 20 virtual TestResult doTest(std::vector<const PassInfo*> &Prefix, 21 std::vector<const PassInfo*> &Suffix); 22}; 23 24ReduceMiscompilingPasses::TestResult 25ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix, 26 std::vector<const PassInfo*> &Suffix) { 27 // First, run the program with just the Suffix passes. If it is still broken 28 // with JUST the kept passes, discard the prefix passes. 29 std::cout << "Checking to see if '" << getPassesString(Suffix) 30 << "' compile correctly: "; 31 32 std::string BytecodeResult; 33 if (BD.runPasses(Suffix, BytecodeResult, false/*delete*/, true/*quiet*/)) { 34 std::cerr << " Error running this sequence of passes" 35 << " on the input program!\n"; 36 BD.setPassesToRun(Suffix); 37 BD.EmitProgressBytecode("pass-error", false); 38 exit(1); 39 } 40 41 // Check to see if the finished program matches the reference output... 42 if (BD.diffProgram(BytecodeResult, "", true /*delete bytecode*/)) { 43 std::cout << "nope.\n"; 44 return KeepSuffix; // Miscompilation detected! 45 } 46 std::cout << "yup.\n"; // No miscompilation! 47 48 if (Prefix.empty()) return NoFailure; 49 50 // Next, see if the program is broken if we run the "prefix" passes first, 51 // then separately run the "kept" passes. 52 std::cout << "Checking to see if '" << getPassesString(Prefix) 53 << "' compile correctly: "; 54 55 // If it is not broken with the kept passes, it's possible that the prefix 56 // passes must be run before the kept passes to break it. If the program 57 // WORKS after the prefix passes, but then fails if running the prefix AND 58 // kept passes, we can update our bytecode file to include the result of the 59 // prefix passes, then discard the prefix passes. 60 // 61 if (BD.runPasses(Prefix, BytecodeResult, false/*delete*/, true/*quiet*/)) { 62 std::cerr << " Error running this sequence of passes" 63 << " on the input program!\n"; 64 BD.setPassesToRun(Prefix); 65 BD.EmitProgressBytecode("pass-error", false); 66 exit(1); 67 } 68 69 // If the prefix maintains the predicate by itself, only keep the prefix! 70 if (BD.diffProgram(BytecodeResult)) { 71 std::cout << "nope.\n"; 72 removeFile(BytecodeResult); 73 return KeepPrefix; 74 } 75 std::cout << "yup.\n"; // No miscompilation! 76 77 // Ok, so now we know that the prefix passes work, try running the suffix 78 // passes on the result of the prefix passes. 79 // 80 Module *PrefixOutput = BD.ParseInputFile(BytecodeResult); 81 if (PrefixOutput == 0) { 82 std::cerr << BD.getToolName() << ": Error reading bytecode file '" 83 << BytecodeResult << "'!\n"; 84 exit(1); 85 } 86 removeFile(BytecodeResult); // No longer need the file on disk 87 88 std::cout << "Checking to see if '" << getPassesString(Suffix) 89 << "' passes compile correctly after the '" 90 << getPassesString(Prefix) << "' passes: "; 91 92 Module *OriginalInput = BD.Program; 93 BD.Program = PrefixOutput; 94 if (BD.runPasses(Suffix, BytecodeResult, false/*delete*/, true/*quiet*/)) { 95 std::cerr << " Error running this sequence of passes" 96 << " on the input program!\n"; 97 BD.setPassesToRun(Suffix); 98 BD.EmitProgressBytecode("pass-error", false); 99 exit(1); 100 } 101 102 // Run the result... 103 if (BD.diffProgram(BytecodeResult, "", true/*delete bytecode*/)) { 104 std::cout << "nope.\n"; 105 delete OriginalInput; // We pruned down the original input... 106 return KeepSuffix; 107 } 108 109 // Otherwise, we must not be running the bad pass anymore. 110 std::cout << "yup.\n"; // No miscompilation! 111 BD.Program = OriginalInput; // Restore original program 112 delete PrefixOutput; // Free experiment 113 return NoFailure; 114} 115 116class ReduceMiscompilingFunctions : public ListReducer<Function*> { 117 BugDriver &BD; 118public: 119 ReduceMiscompilingFunctions(BugDriver &bd) : BD(bd) {} 120 121 virtual TestResult doTest(std::vector<Function*> &Prefix, 122 std::vector<Function*> &Suffix) { 123 if (!Suffix.empty() && TestFuncs(Suffix, false)) 124 return KeepSuffix; 125 if (!Prefix.empty() && TestFuncs(Prefix, false)) 126 return KeepPrefix; 127 return NoFailure; 128 } 129 130 bool TestFuncs(const std::vector<Function*> &Prefix, bool EmitBytecode); 131}; 132 133bool ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function*> &Funcs, 134 bool EmitBytecode) { 135 // Test to see if the function is misoptimized if we ONLY run it on the 136 // functions listed in Funcs. 137 if (!EmitBytecode) { 138 std::cout << "Checking to see if the program is misoptimized when these " 139 << "functions are run\nthrough the passes: "; 140 BD.PrintFunctionList(Funcs); 141 std::cout << "\n"; 142 } else { 143 std::cout <<"Outputting reduced bytecode files which expose the problem:\n"; 144 } 145 146 // First step: clone the module for the two halves of the program we want. 147 Module *ToOptimize = CloneModule(BD.Program); 148 149 // Second step: Make sure functions & globals are all external so that linkage 150 // between the two modules will work. 151 for (Module::iterator I = ToOptimize->begin(), E = ToOptimize->end();I!=E;++I) 152 I->setLinkage(GlobalValue::ExternalLinkage); 153 for (Module::giterator I = ToOptimize->gbegin(), E = ToOptimize->gend(); 154 I != E; ++I) 155 I->setLinkage(GlobalValue::ExternalLinkage); 156 157 // Third step: make a clone of the externalized program for the non-optimized 158 // part. 159 Module *ToNotOptimize = CloneModule(ToOptimize); 160 161 // Fourth step: Remove the test functions from the ToNotOptimize module, and 162 // all of the global variables. 163 for (unsigned i = 0, e = Funcs.size(); i != e; ++i) { 164 Function *TNOF = ToNotOptimize->getFunction(Funcs[i]->getName(), 165 Funcs[i]->getFunctionType()); 166 assert(TNOF && "Function doesn't exist in module!"); 167 DeleteFunctionBody(TNOF); // Function is now external in this module! 168 } 169 for (Module::giterator I = ToNotOptimize->gbegin(), E = ToNotOptimize->gend(); 170 I != E; ++I) 171 I->setInitializer(0); // Delete the initializer to make it external 172 173 if (EmitBytecode) { 174 std::cout << " Non-optimized portion: "; 175 std::swap(BD.Program, ToNotOptimize); 176 BD.EmitProgressBytecode("tonotoptimize", true); 177 std::swap(BD.Program, ToNotOptimize); 178 } 179 180 // Fifth step: Remove all functions from the ToOptimize module EXCEPT for the 181 // ones specified in Funcs. We know which ones these are because they are 182 // non-external in ToOptimize, but external in ToNotOptimize. 183 // 184 for (Module::iterator I = ToOptimize->begin(), E = ToOptimize->end();I!=E;++I) 185 if (!I->isExternal()) { 186 Function *TNOF = ToNotOptimize->getFunction(I->getName(), 187 I->getFunctionType()); 188 assert(TNOF && "Function doesn't exist in ToNotOptimize module??"); 189 if (!TNOF->isExternal()) 190 DeleteFunctionBody(I); 191 } 192 193 if (EmitBytecode) { 194 std::cout << " Portion that is input to optimizer: "; 195 std::swap(BD.Program, ToOptimize); 196 BD.EmitProgressBytecode("tooptimize"); 197 std::swap(BD.Program, ToOptimize); 198 } 199 200 // Sixth step: Run the optimization passes on ToOptimize, producing a 201 // transformed version of the functions being tested. 202 Module *OldProgram = BD.Program; 203 BD.Program = ToOptimize; 204 205 if (!EmitBytecode) 206 std::cout << " Optimizing functions being tested: "; 207 std::string BytecodeResult; 208 if (BD.runPasses(BD.PassesToRun, BytecodeResult, false/*delete*/, 209 true/*quiet*/)) { 210 std::cerr << " Error running this sequence of passes" 211 << " on the input program!\n"; 212 BD.EmitProgressBytecode("pass-error", false); 213 exit(1); 214 } 215 216 if (!EmitBytecode) 217 std::cout << "done.\n"; 218 219 delete BD.Program; // Delete the old "ToOptimize" module 220 BD.Program = BD.ParseInputFile(BytecodeResult); 221 222 if (EmitBytecode) { 223 std::cout << " 'tooptimize' after being optimized: "; 224 BD.EmitProgressBytecode("optimized", true); 225 } 226 227 if (BD.Program == 0) { 228 std::cerr << BD.getToolName() << ": Error reading bytecode file '" 229 << BytecodeResult << "'!\n"; 230 exit(1); 231 } 232 removeFile(BytecodeResult); // No longer need the file on disk 233 234 // Seventh step: Link the optimized part of the program back to the 235 // unoptimized part of the program. 236 // 237 if (LinkModules(BD.Program, ToNotOptimize, &BytecodeResult)) { 238 std::cerr << BD.getToolName() << ": Error linking modules together:" 239 << BytecodeResult << "\n"; 240 exit(1); 241 } 242 delete ToNotOptimize; // We are done with this module... 243 244 if (EmitBytecode) { 245 std::cout << " Program as tested: "; 246 BD.EmitProgressBytecode("linked", true); 247 delete BD.Program; 248 BD.Program = OldProgram; 249 return false; // We don't need to actually execute the program here. 250 } 251 252 std::cout << " Checking to see if the merged program executes correctly: "; 253 254 // Eighth step: Execute the program. If it does not match the expected 255 // output, then 'Funcs' are being misoptimized! 256 bool Broken = BD.diffProgram(); 257 258 delete BD.Program; // Delete the hacked up program 259 BD.Program = OldProgram; // Restore the original 260 261 std::cout << (Broken ? "nope.\n" : "yup.\n"); 262 return Broken; 263} 264 265 266/// debugMiscompilation - This method is used when the passes selected are not 267/// crashing, but the generated output is semantically different from the 268/// input. 269/// 270bool BugDriver::debugMiscompilation() { 271 // Make sure something was miscompiled... 272 if (!ReduceMiscompilingPasses(*this).reduceList(PassesToRun)) { 273 std::cerr << "*** Optimized program matches reference output! No problem " 274 << "detected...\nbugpoint can't help you with your problem!\n"; 275 return false; 276 } 277 278 std::cout << "\n*** Found miscompiling pass" 279 << (PassesToRun.size() == 1 ? "" : "es") << ": " 280 << getPassesString(PassesToRun) << "\n"; 281 EmitProgressBytecode("passinput"); 282 283 // Okay, now that we have reduced the list of passes which are causing the 284 // failure, see if we can pin down which functions are being 285 // miscompiled... first build a list of all of the non-external functions in 286 // the program. 287 std::vector<Function*> MiscompiledFunctions; 288 for (Module::iterator I = Program->begin(), E = Program->end(); I != E; ++I) 289 if (!I->isExternal()) 290 MiscompiledFunctions.push_back(I); 291 292 // Do the reduction... 293 ReduceMiscompilingFunctions(*this).reduceList(MiscompiledFunctions); 294 295 std::cout << "\n*** The following functions are being miscompiled: "; 296 PrintFunctionList(MiscompiledFunctions); 297 std::cout << "\n"; 298 299 // Output a bunch of bytecode files for the user... 300 ReduceMiscompilingFunctions(*this).TestFuncs(MiscompiledFunctions, true); 301 302 return false; 303} 304