1 //===- CodeGeneratorBug.cpp - Debug code generation bugs ------------------===//
3 // This file implements program code generation debugging support.
5 //===----------------------------------------------------------------------===//
8 #include "SystemUtils.h"
9 #include "ListReducer.h"
10 #include "llvm/Pass.h"
11 #include "llvm/Module.h"
12 #include "llvm/Transforms/Utils/Cloning.h"
13 #include "llvm/Transforms/Utils/Linker.h"
14 #include "Support/CommandLine.h"
15 #include "Support/Statistic.h"
16 #include "Support/StringExtras.h"
20 // Passed as a command-line argument to Bugpoint
21 extern cl::opt<std::string> Output;
23 class ReduceMisCodegenFunctions : public ListReducer<Function*> {
26 ReduceMisCodegenFunctions(BugDriver &bd) : BD(bd) {}
28 virtual TestResult doTest(std::vector<Function*> &Prefix,
29 std::vector<Function*> &Suffix) {
30 if (!Prefix.empty() && TestFuncs(Prefix))
32 if (!Suffix.empty() && TestFuncs(Suffix))
37 bool TestFuncs(const std::vector<Function*> &CodegenTest);
39 void DisambiguateGlobalSymbols(Module *M);
43 bool ReduceMisCodegenFunctions::TestFuncs(const std::vector<Function*> &Funcs)
45 // Clone the module for the two halves of the program we want.
46 Module *SafeModule = CloneModule(BD.Program);
48 // Make sure functions & globals are all external so that linkage
49 // between the two modules will work.
50 for (Module::iterator I = SafeModule->begin(), E = SafeModule->end();I!=E;++I)
51 I->setLinkage(GlobalValue::ExternalLinkage);
52 for (Module::giterator I=SafeModule->gbegin(),E = SafeModule->gend();I!=E;++I)
53 I->setLinkage(GlobalValue::ExternalLinkage);
55 DisambiguateGlobalSymbols(SafeModule);
56 Module *TestModule = CloneModule(SafeModule);
58 // Make sure global initializers exist only in the safe module (CBE->.so)
59 for (Module::giterator I=TestModule->gbegin(),E = TestModule->gend();I!=E;++I)
60 I->setInitializer(0); // Delete the initializer to make it external
62 // Remove the Test functions from the Safe module, and
63 // all of the global variables.
64 for (unsigned i = 0, e = Funcs.size(); i != e; ++i) {
65 Function *TNOF = SafeModule->getFunction(Funcs[i]->getName(),
66 Funcs[i]->getFunctionType());
67 assert(TNOF && "Function doesn't exist in module!");
68 DeleteFunctionBody(TNOF); // Function is now external in this module!
71 // Write out the bytecode to be sent to CBE
72 std::string SafeModuleBC = "bugpoint.safe.bc";
73 if (BD.writeProgramToFile(SafeModuleBC, SafeModule)) {
74 std::cerr << "Error writing bytecode to `" << SafeModuleBC << "'\nExiting.";
78 // Make a shared library
79 std::string SharedObject;
80 BD.compileSharedObject(SafeModuleBC, SharedObject);
82 // Remove all functions from the Test module EXCEPT for the ones specified in
83 // Funcs. We know which ones these are because they are non-external in
84 // ToOptimize, but external in ToNotOptimize.
86 for (Module::iterator I = TestModule->begin(), E = TestModule->end();I!=E;++I)
87 if (!I->isExternal()) {
88 Function *TNOF = SafeModule->getFunction(I->getName(),
89 I->getFunctionType());
90 assert(TNOF && "Function doesn't exist in ToNotOptimize module??");
91 if (!TNOF->isExternal())
92 DeleteFunctionBody(I);
95 std::string TestModuleBC = "bugpoint.test.bc";
96 if (BD.writeProgramToFile(TestModuleBC, TestModule)) {
97 std::cerr << "Error writing bytecode to `" << SafeModuleBC << "'\nExiting.";
101 // Run the code generator on the `Test' code, loading the shared library.
102 // The function returns whether or not the new output differs from reference.
103 return BD.diffProgram(TestModuleBC, SharedObject, false);
107 struct Disambiguator /*: public unary_function<GlobalValue&, void>*/ {
108 std::set<std::string> SymbolNames;
109 std::set<Value*> Symbols;
110 uint64_t uniqueCounter;
113 Disambiguator() : uniqueCounter(0), externalOnly(true) {}
114 void setExternalOnly(bool value) { externalOnly = value; }
115 void operator() (GlobalValue &V) {
116 if (externalOnly && !V.isExternal()) return;
118 if (SymbolNames.count(V.getName()) == 0) {
119 DEBUG(std::cerr << "Disambiguator: adding " << V.getName()
120 << ", no conflicts.\n");
122 SymbolNames.insert(V.getName());
124 // Mangle name before adding
127 newName = V.getName() + "_" + utostr(uniqueCounter);
128 if (SymbolNames.count(newName) == 0) break;
129 else ++uniqueCounter;
131 //while (SymbolNames.count(V->getName()+utostr(uniqueCounter++))==0);
132 DEBUG(std::cerr << "Disambiguator: conflict: " << V.getName()
133 << ", adding: " << newName << "\n");
135 SymbolNames.insert(newName);
142 void ReduceMisCodegenFunctions::DisambiguateGlobalSymbols(Module *M) {
143 // First, try not to cause collisions by minimizing chances of renaming an
144 // already-external symbol, so take in external globals and functions as-is.
145 Disambiguator D = std::for_each(M->gbegin(), M->gend(), Disambiguator());
146 std::for_each(M->begin(), M->end(), D);
148 // Now just rename functions and globals as necessary, keeping what's already
149 // in the set unique.
150 D.setExternalOnly(false);
151 std::for_each(M->gbegin(), M->gend(), D);
152 std::for_each(M->begin(), M->end(), D);
156 bool BugDriver::debugCodeGenerator() {
157 // See if we can pin down which functions are being miscompiled...
158 //First, build a list of all of the non-external functions in the program.
159 std::vector<Function*> MisCodegenFunctions;
160 for (Module::iterator I = Program->begin(), E = Program->end(); I != E; ++I)
161 if (!I->isExternal())
162 MisCodegenFunctions.push_back(I);
164 // Do the reduction...
165 ReduceMisCodegenFunctions(*this).reduceList(MisCodegenFunctions);
167 std::cout << "\n*** The following functions are being miscompiled: ";
168 PrintFunctionList(MisCodegenFunctions);
171 // Output a bunch of bytecode files for the user...
172 ReduceMisCodegenFunctions(*this).TestFuncs(MisCodegenFunctions);