Misc enhancements to LTO:
[oota-llvm.git] / tools / lto / LTOPartition.cpp
1 //===-- LTOPartition.cpp - Parition Merged Module --------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "LTOPartition.h"
11 #include "llvm/ADT/SetVector.h"
12 #include "llvm/ADT/DenseMap.h"
13 #include "llvm/Analysis/CallGraph.h"
14 #include "llvm/Bitcode/ReaderWriter.h"
15 #include "llvm/IR/Module.h"
16 #include "llvm/Support/FileSystem.h"
17 #include "llvm/Support/MemoryBuffer.h"
18 #include "llvm/Support/SourceMgr.h"
19 #include "llvm/Support/raw_ostream.h"
20 #include "llvm/Support/Path.h"
21 #include "llvm/Transforms/Utils/ValueMapper.h"
22 #include "llvm/Transforms/Utils/Cloning.h"
23
24 using namespace llvm;
25 using namespace lto;
26
27 // /////////////////////////////////////////////////////////////////////////////
28 //
29 //   Implementation of IPOPartition and IPOPartMgr
30 //
31 // /////////////////////////////////////////////////////////////////////////////
32 //
33 IPOPartition::IPOPartition(Module *M, const char *NameWoExt, IPOFileMgr &FM) :
34   Mod(0), Ctx(0), IRFile(0), ObjFile(0), FileNameWoExt(NameWoExt), FileMgr(FM) {
35 }
36
37 IPOFile &IPOPartition::getIRFile() const {
38   if (IRFile)
39     return *IRFile;
40   else {
41     std::string FN(FileNameWoExt + ".bc");
42     return *(IRFile = FileMgr.createIRFile(FN.c_str()));
43   }
44 }
45
46 IPOFile &IPOPartition::getObjFile() const {
47   if (ObjFile)
48     return *ObjFile;
49   else {
50     std::string FN(FileNameWoExt + ".o");
51     return *(ObjFile = FileMgr.createObjFile(FN.c_str()));
52   }
53 }
54
55 bool IPOPartition::saveBitCode() {
56   if (!Mod) {
57     // The bit-code have already saved in disk.
58     return true;
59   }
60
61   IPOFile &F = getIRFile();
62   if (F.errOccur())
63     return false;
64
65   raw_fd_ostream OF(F.getPath().c_str(), F.getLastErrStr(),
66                     sys::fs::F_Binary);
67   WriteBitcodeToFile(Mod, OF);
68   OF.close();
69
70   Mod = 0;
71   delete Ctx;
72   Ctx = 0;
73  
74   return !F.errOccur();
75 }
76
77 bool IPOPartition::loadBitCode() {
78   if (Mod)
79     return true;
80
81   IPOFile &F = getIRFile();
82   if (F.errOccur())
83     return false;
84
85   Ctx = new LLVMContext;
86
87   error_code &EC = F.getLastErrCode();
88   std::string &ErrMsg = F.getLastErrStr();
89
90   OwningPtr<MemoryBuffer> Buf;
91   if (error_code ec = MemoryBuffer::getFile(F.getPath(), Buf, -1, false)) {
92     EC = ec; 
93     ErrMsg += ec.message();
94     return false;
95   }
96
97   Mod = ParseBitcodeFile(Buf.get(), *Ctx, &ErrMsg);
98
99   return Mod != 0;
100 }
101
102 IPOPartition *IPOPartMgr::createIPOPart(Module *M) {
103   std::string PartName;
104   raw_string_ostream OS(PartName); 
105   OS << "part" << NextPartId++;
106
107   IPOPartition *P = new IPOPartition(M, OS.str().c_str(), FileMgr);
108   P->Mod = M;
109   IPOParts.push_back(P);
110   return P;
111 }
112
113 // ///////////////////////////////////////////////////////////////////////////
114 //
115 //      Implementation of IPOFile and IPOFileMgr 
116 //  
117 // ///////////////////////////////////////////////////////////////////////////
118 //
119 IPOFile::IPOFile(const char *DirName, const char *BaseName, bool KeepFile)
120   : Fname(BaseName), Keep(KeepFile) {
121   // Concatenate dirname and basename
122   StringRef D(DirName);
123   SmallVector<char, 64> Path(D.begin(), D.end());
124   sys::path::append(Path, Twine(BaseName));
125   Fpath = StringRef(Path.data(), Path.size());
126 }
127
128 IPOFileMgr::IPOFileMgr() {
129   IRFiles.reserve(20);
130   ObjFiles.reserve(20);
131   OtherFiles.reserve(8);
132   KeepWorkDir = false;
133   WorkDirCreated = false;
134 }
135
136 bool IPOFileMgr::createWorkDir(std::string &ErrorInfo) {
137   if (WorkDirCreated)
138     return true;
139
140   error_code EC;
141   if (WorkDir.empty()) {
142     // If the workdir is not specified, then create workdir under current
143     // directory.
144     //
145     SmallString<128> D;
146     if (sys::fs::current_path(D) != error_code::success()) {
147       ErrorInfo += "fail to get current directory";
148       return false;
149     }
150     sys::path::append(D, "llvmipo");
151     sys::fs::make_absolute(D);
152
153     SmallVector<char, 64> ResPath;
154     EC = sys::fs::createUniqueDirectory(Twine(StringRef(D.data(), D.size())),
155                                         ResPath);
156     WorkDir = StringRef(ResPath.data(), ResPath.size());
157   } else {
158     bool Exist;
159     EC = sys::fs::create_directory(Twine(WorkDir), Exist);
160   }
161
162   if (EC == error_code::success()) {
163     WorkDirCreated = true;
164     return true;
165   }
166  
167   return false;
168 }
169
170 IPOFile *IPOFileMgr::createIRFile(const char *Name) {
171   IPOFile *F = CreateFile(Name);
172   IRFiles.push_back(F);
173   return F;
174 }
175
176 IPOFile *IPOFileMgr::createObjFile(const char *Name) {
177   IPOFile *F = CreateFile(Name);
178   ObjFiles.push_back(F);
179   return F;
180 }
181
182 IPOFile *IPOFileMgr::createMakefile(const char *Name) {
183   IPOFile *F = CreateFile(Name);
184   OtherFiles.push_back(F);
185   return F;
186 }
187
188 void IPOFileMgr::removeAllUnneededFiles() {
189   FileNameVect ToRm;
190   getFilesNeedToRemove(ToRm);
191
192   for (SmallVector<const char *, 4>::iterator I = ToRm.begin(), E = ToRm.end();
193        I != E; I++) {
194     const char *FN = *I;
195     sys::fs::file_status Stat;
196     if (sys::fs::status(Twine(FN), Stat) != error_code::success())
197       continue;
198
199     uint32_t Dummy;
200     if (sys::fs::is_directory(FN))
201       sys::fs::remove_all(Twine(FN), Dummy);
202     else
203       sys::fs::remove(Twine(FN));
204   }
205 }