1 //===- LTOBugPoint.cpp - Top-Level LTO BugPoint class ---------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This class contains all of the shared state and information that is used by
11 // the LTO BugPoint tool to track down bit code files that cause errors.
13 //===----------------------------------------------------------------------===//
15 #include "LTOBugPoint.h"
16 #include "llvm/PassManager.h"
17 #include "llvm/Module.h"
18 #include "llvm/ModuleProvider.h"
19 #include "llvm/CodeGen/FileWriters.h"
20 #include "llvm/Target/SubtargetFeature.h"
21 #include "llvm/Target/TargetOptions.h"
22 #include "llvm/Target/TargetMachine.h"
23 #include "llvm/Target/TargetData.h"
24 #include "llvm/Target/TargetAsmInfo.h"
25 #include "llvm/Target/TargetMachineRegistry.h"
26 #include "llvm/Support/SystemUtils.h"
27 #include "llvm/Support/MemoryBuffer.h"
28 #include "llvm/Bitcode/ReaderWriter.h"
29 #include "llvm/System/Path.h"
30 #include "llvm/Config/config.h"
35 using namespace Reloc;
36 /// LTOBugPoint -- Constructor. Popuate list of linker options and
37 /// list of linker input files.
38 LTOBugPoint::LTOBugPoint(std::istream &args, std::istream &ins) {
40 // Read linker options. Order is important here.
42 while (getline(args, option))
43 LinkerOptions.push_back(option);
45 // Read linker input files. Order is important here.
47 while(getline(ins, inFile))
48 LinkerInputFiles.push_back(inFile);
51 /// findTroubleMakers - Find minimum set of input files that causes error
52 /// identified by the script.
54 LTOBugPoint::findTroubleMakers(SmallVector<std::string, 4> &TroubleMakers,
55 std::string &Script) {
57 // First, build native object files set.
58 bool bitcodeFileSeen = false;
59 unsigned Size = LinkerInputFiles.size();
60 for (unsigned I = 0; I < Size; ++I) {
61 std::string &FileName = LinkerInputFiles[I];
62 sys::Path InputFile(FileName.c_str());
63 if (InputFile.isDynamicLibrary() || InputFile.isArchive()) {
64 ErrMsg = "Unable to handle input file ";
68 else if (InputFile.isBitcodeFile()) {
69 bitcodeFileSeen = true;
70 if (getNativeObjectFile(FileName) == false)
74 NativeInputFiles.push_back(FileName);
77 if (!bitcodeFileSeen) {
78 ErrMsg = "Unable to help!";
79 ErrMsg += " Need at least one input file that contains llvm bitcode";
86 /// getFeatureString - Return a string listing the features associated with the
89 /// FIXME: This is an inelegant way of specifying the features of a
90 /// subtarget. It would be better if we could encode this information into the
92 std::string LTOBugPoint::getFeatureString(const char *TargetTriple) {
93 SubtargetFeatures Features;
95 if (strncmp(TargetTriple, "powerpc-apple-", 14) == 0) {
96 Features.AddFeature("altivec", true);
97 } else if (strncmp(TargetTriple, "powerpc64-apple-", 16) == 0) {
98 Features.AddFeature("64bit", true);
99 Features.AddFeature("altivec", true);
102 return Features.getString();
105 /// assembleBitcode - Generate assembly code from the module. Return false
106 /// in case of an error.
107 bool LTOBugPoint::assembleBitcode(llvm::Module *M, const char *AsmFileName) {
108 std::string TargetTriple = M->getTargetTriple();
109 std::string FeatureStr =
110 getFeatureString(TargetTriple.c_str());
112 const TargetMachineRegistry::entry* Registry =
113 TargetMachineRegistry::getClosestStaticTargetForModule(
115 if ( Registry == NULL )
118 TargetMachine *Target = Registry->CtorFn(*M, FeatureStr.c_str());
120 // If target supports exception handling then enable it now.
121 if (Target->getTargetAsmInfo()->doesSupportExceptionHandling())
122 ExceptionHandling = true;
125 Target->setRelocationModel(Reloc::PIC_);
127 FunctionPassManager* CGPasses =
128 new FunctionPassManager(new ExistingModuleProvider(M));
130 CGPasses->add(new TargetData(*Target->getTargetData()));
131 MachineCodeEmitter* mce = NULL;
133 std::ofstream *Out = new std::ofstream(AsmFileName, std::ios::out);
135 switch (Target->addPassesToEmitFile(*CGPasses, *Out,
136 TargetMachine::AssemblyFile, true)) {
137 case FileModel::MachOFile:
138 mce = AddMachOWriter(*CGPasses, *Out, *Target);
140 case FileModel::ElfFile:
141 mce = AddELFWriter(*CGPasses, *Out, *Target);
143 case FileModel::AsmFile:
145 case FileModel::Error:
146 case FileModel::None:
147 ErrMsg = "target file type not supported";
151 if (Target->addPassesToEmitFileFinish(*CGPasses, mce, true)) {
152 ErrMsg = "target does not support generation of this file type";
156 CGPasses->doInitialization();
157 for (Module::iterator
158 it = M->begin(), e = M->end(); it != e; ++it)
159 if (!it->isDeclaration())
161 CGPasses->doFinalization();
166 /// getNativeObjectFile - Generate native object file based from llvm
167 /// bitcode file. Return false in case of an error.
168 bool LTOBugPoint::getNativeObjectFile(std::string &FileName) {
170 std::auto_ptr<Module> M;
172 = MemoryBuffer::getFile(FileName.c_str(), &ErrMsg);
174 ErrMsg = "Unable to read ";
178 M.reset(ParseBitcodeFile(Buffer, &ErrMsg));
179 std::string TargetTriple = M->getTargetTriple();
181 sys::Path AsmFile(sys::Path::GetTemporaryDirectory());
182 if(AsmFile.createTemporaryFileOnDisk(false, &ErrMsg))
185 if (assembleBitcode(M.get(), AsmFile.c_str()) == false)
188 sys::Path NativeFile(sys::Path::GetTemporaryDirectory());
189 if(NativeFile.createTemporaryFileOnDisk(false, &ErrMsg))
192 // find compiler driver
193 const sys::Path gcc = sys::Program::FindProgramByName("gcc");
194 if ( gcc.isEmpty() ) {
195 ErrMsg = "can't locate gcc";
199 // build argument list
200 std::vector<const char*> args;
201 args.push_back(gcc.c_str());
202 if ( TargetTriple.find("darwin") != TargetTriple.size() ) {
203 if (strncmp(TargetTriple.c_str(), "i686-apple-", 11) == 0) {
204 args.push_back("-arch");
205 args.push_back("i386");
207 else if (strncmp(TargetTriple.c_str(), "x86_64-apple-", 13) == 0) {
208 args.push_back("-arch");
209 args.push_back("x86_64");
211 else if (strncmp(TargetTriple.c_str(), "powerpc-apple-", 14) == 0) {
212 args.push_back("-arch");
213 args.push_back("ppc");
215 else if (strncmp(TargetTriple.c_str(), "powerpc64-apple-", 16) == 0) {
216 args.push_back("-arch");
217 args.push_back("ppc64");
220 args.push_back("-c");
221 args.push_back("-x");
222 args.push_back("assembler");
223 args.push_back("-o");
224 args.push_back(NativeFile.c_str());
225 args.push_back(AsmFile.c_str());
229 if (sys::Program::ExecuteAndWait(gcc, &args[0], 0, 0, 0, 0, &ErrMsg)) {
230 ErrMsg = "error in assembly";