llvm.org GIT mirror llvm / 67d135a
Misc enhancements to LTO: 1. Add some helper classes for partitions. They are designed in a way such that the top-level LTO driver will not see much difference with or without partitioning. 2. Introduce work-dir. Now all intermediate files generated during LTO phases will be saved under work-dir. User can specify the workdir via -lto-workdir=/path/to/dir. By default the work-dir will be erased before linker exit. To keep the workdir, do -lto-keep, or -lto-keep=1. TODO: Erase the workdir, if the linker exit prematurely. We are currently not able to remove directory on signal. The support routines simply ignore directory. 3. Add one new API lto_codegen_get_files_need_remove(). Linker and LTO plugin will communicate via this API about which files (including directories) need to removed before linker exit. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@188188 91177308-0d34-0410-b5e6-96231b3b80d8 Shuxin Yang 7 years ago
11 changed file(s) with 884 addition(s) and 56 deletion(s). Raw diff Collapse all Expand all
283283 extern bool
284284 lto_codegen_compile_to_file(lto_code_gen_t cg, const char** name);
285285
286 /**
287 * Get intermediate files that need to be removed before linker exit. Upon
288 * return, the paths of the files need to be removed is written to "paths". The
289 * paths are separated by a single '\0', and the last path is ended by double
290 * '\0's. A file could be a directory; in this case, the entire directory needs
291 * to be removed recursively.
292 *
293 * It is only necessary to call this function after \p lto_codegen_compile was
294 * successfully called.
295 */
296 extern void
297 lto_codegen_get_files_need_remove(lto_code_gen_t cg, const char **paths);
286298
287299 /**
288300 * Sets options to help debug codegen bugs.
7373 static bool generate_api_file = false;
7474 static generate_bc generate_bc_file = BC_NO;
7575 static std::string bc_path;
76 static std::string obj_path;
7776 static std::string extra_library_path;
7877 static std::string triple;
7978 static std::string mcpu;
9897 extra_library_path = opt.substr(strlen("extra_library_path="));
9998 } else if (opt.startswith("mtriple=")) {
10099 triple = opt.substr(strlen("mtriple="));
101 } else if (opt.startswith("obj-path=")) {
102 obj_path = opt.substr(strlen("obj-path="));
103100 } else if (opt == "emit-llvm") {
104101 generate_bc_file = BC_ONLY;
105102 } else if (opt == "also-emit-llvm") {
424421 (*message)(LDPL_ERROR, "Could not produce a combined object file\n");
425422 }
426423
424 // Get files that need to be removed in cleanup_hook.
425 const char *ToRm;
426 lto_codegen_get_files_need_remove(code_gen, &ToRm);
427 while (*ToRm) {
428 Cleanup.push_back(std::string(ToRm));
429 ToRm += strlen(ToRm) + 1;
430 }
431
427432 lto_codegen_dispose(code_gen);
428433 for (std::list::iterator I = Modules.begin(),
429434 E = Modules.end(); I != E; ++I) {
445450 return LDPS_ERR;
446451 }
447452
448 if (options::obj_path.empty())
449 Cleanup.push_back(objPath);
450
451453 return LDPS_OK;
452454 }
453455
454456 static ld_plugin_status cleanup_hook(void) {
455457 for (int i = 0, e = Cleanup.size(); i != e; ++i) {
456 error_code EC = sys::fs::remove(Cleanup[i]);
458 const char *FN = Cleanup[i].c_str();
459 sys::fs::file_status Stat;
460 error_code EC = sys::fs::status(Twine(FN), Stat);
461 if (EC) {
462 (*message)(LDPL_ERROR, "Failed to stat '%s': %s", FN,
463 EC.message().c_str());
464 continue;
465 }
466
467 uint32_t Dummy;
468 if (sys::fs::is_directory(FN))
469 EC = sys::fs::remove_all(Twine(FN), Dummy);
470 else
471 EC = sys::fs::remove(Twine(FN));
472
457473 if (EC)
458 (*message)(LDPL_ERROR, "Failed to delete '%s': %s", Cleanup[i].c_str(),
474 (*message)(LDPL_ERROR, "Failed to remove '%s': %s", FN,
459475 EC.message().c_str());
460476 }
461477
88 LTODisassembler.cpp
99 lto.cpp
1010 LTOModule.cpp
11 LTOPartition.cpp
12 LTOPostIPODriver.cpp
1113 )
1214
1315 set(LLVM_COMMON_DEPENDS intrinsics_gen)
1313
1414 #include "LTOCodeGenerator.h"
1515 #include "LTOModule.h"
16 #include "LTOPartition.h"
17 #include "LTOPostIPODriver.h"
1618 #include "llvm/ADT/StringExtras.h"
1719 #include "llvm/Analysis/Passes.h"
1820 #include "llvm/Analysis/Verifier.h"
3436 #include "llvm/Support/FormattedStream.h"
3537 #include "llvm/Support/Host.h"
3638 #include "llvm/Support/MemoryBuffer.h"
39 #include "llvm/Support/Program.h"
3740 #include "llvm/Support/Signals.h"
3841 #include "llvm/Support/TargetRegistry.h"
3942 #include "llvm/Support/TargetSelect.h"
4043 #include "llvm/Support/ToolOutputFile.h"
4144 #include "llvm/Support/system_error.h"
45 #include "llvm/Support/SourceMgr.h"
4246 #include "llvm/Target/Mangler.h"
4347 #include "llvm/Target/TargetMachine.h"
4448 #include "llvm/Target/TargetOptions.h"
4650 #include "llvm/Transforms/IPO.h"
4751 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
4852 #include "llvm/Transforms/ObjCARC.h"
53
4954 using namespace llvm;
50
55 using namespace lto;
56
57 // /////////////////////////////////////////////////////////////////////////////
58 //
59 // Internal options. To avoid collision, most options start with "lto-".
60 //
61 // /////////////////////////////////////////////////////////////////////////////
62 //
5163 static cl::opt
5264 DisableOpt("disable-opt", cl::init(false),
5365 cl::desc("Do not run any optimization passes"));
6072 DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false),
6173 cl::desc("Do not run the GVN load PRE pass"));
6274
75 // To break merged module into partitions, and compile them independently.
76 static cl::opt
77 EnablePartition("lto-partition", cl::init(false),
78 cl::desc("Partition program and compile each piece in parallel"));
79
80 // Specify the work-directory for the LTO compilation. All intermeidate
81 // files will be created immediately under this dir. If it is not
82 // specified, compiler will create an unique directory under current-dir.
83 //
84 static cl::opt
85 TmpWorkDir("lto-workdir", cl::init(""), cl::desc("Specify working directory"));
86
87 static cl::opt
88 KeepWorkDir("lto-keep", cl::init(false), cl::desc("Keep working directory"));
89
90
91 // /////////////////////////////////////////////////////////////////////////////
92 //
93 // Implementation of LTOCodeGenerator
94 //
95 // /////////////////////////////////////////////////////////////////////////////
96 //
6397 const char* LTOCodeGenerator::getVersionString() {
6498 #ifdef LLVM_VERSION_INFO
6599 return PACKAGE_NAME " version " PACKAGE_VERSION ", " LLVM_VERSION_INFO;
73107 _linker(new Module("ld-temp.o", _context)), _target(NULL),
74108 _emitDwarfDebugInfo(false), _scopeRestrictionsDone(false),
75109 _codeModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC),
76 _nativeObjectFile(NULL) {
110 _nativeObjectFile(NULL), PartitionMgr(FileMgr),
111 OptionsParsed(false) {
77112 InitializeAllTargets();
78113 InitializeAllTargetMCs();
79114 InitializeAllAsmPrinters();
186221 return true;
187222 }
188223
189 bool LTOCodeGenerator::compile_to_file(const char** name, std::string& errMsg) {
190 // make unique temp .o file to put generated object file
191 SmallString<128> Filename;
192 int FD;
193 error_code EC = sys::fs::createTemporaryFile("lto-llvm", "o", FD, Filename);
194 if (EC) {
195 errMsg = EC.message();
196 return false;
197 }
198
199 // generate object file
200 tool_output_file objFile(Filename.c_str(), FD);
201
202 bool genResult = generateObjectFile(objFile.os(), errMsg);
203 objFile.os().close();
204 if (objFile.os().has_error()) {
205 objFile.os().clear_error();
206 sys::fs::remove(Twine(Filename));
207 return false;
208 }
209
210 objFile.keep();
211 if (!genResult) {
212 sys::fs::remove(Twine(Filename));
213 return false;
214 }
215
216 _nativeObjectPath = Filename.c_str();
217 *name = _nativeObjectPath.c_str();
224 // This function is to ensure cl::ParseCommandLineOptions() is called no more
225 // than once. It would otherwise complain and exit the compilation prematurely.
226 //
227 void LTOCodeGenerator::parseOptions() {
228 if (OptionsParsed)
229 return;
230
231 if (!_codegenOptions.empty())
232 cl::ParseCommandLineOptions(_codegenOptions.size(),
233 const_cast(&_codegenOptions[0]));
234
235 OptionsParsed = true;
236 }
237
238 // Do some prepartion right before compilation starts.
239 bool LTOCodeGenerator::prepareBeforeCompile(std::string &ErrMsg) {
240 parseOptions();
241
242 if (!determineTarget(ErrMsg))
243 return false;
244
245 FileMgr.setWorkDir(TmpWorkDir.c_str());
246 FileMgr.setKeepWorkDir(KeepWorkDir);
247 return FileMgr.createWorkDir(ErrMsg);
248 }
249
250 bool LTOCodeGenerator::compile_to_file(const char** Name, std::string& ErrMsg) {
251 if (!prepareBeforeCompile(ErrMsg))
252 return false;
253
254 performIPO(EnablePartition, ErrMsg);
255 if (!performPostIPO(ErrMsg))
256 return false;
257
258 *Name = PartitionMgr.getSinglePartition()->getObjFilePath().c_str();
218259 return true;
219260 }
220261
228269
229270 // read .o file into memory buffer
230271 OwningPtr BuffPtr;
272 const char *BufStart = 0;
273
231274 if (error_code ec = MemoryBuffer::getFile(name, BuffPtr, -1, false)) {
232275 errMsg = ec.message();
233 sys::fs::remove(_nativeObjectPath);
234 return NULL;
235 }
236 _nativeObjectFile = BuffPtr.take();
237
238 // remove temp files
239 sys::fs::remove(_nativeObjectPath);
240
241 // return buffer, unless error
242 if (_nativeObjectFile == NULL)
243 return NULL;
244 *length = _nativeObjectFile->getBufferSize();
245 return _nativeObjectFile->getBufferStart();
276 _nativeObjectFile = 0;
277 } else {
278 if ((_nativeObjectFile = BuffPtr.take())) {
279 *length = _nativeObjectFile->getBufferSize();
280 BufStart = _nativeObjectFile->getBufferStart();
281 }
282 }
283
284 // Now that the resulting single object file is handed to linker via memory
285 // buffer, it is safe to remove all intermediate files now.
286 //
287 FileMgr.removeAllUnneededFiles();
288
289 return BufStart;
290 }
291
292 const char *LTOCodeGenerator::getFilesNeedToRemove() {
293 IPOFileMgr::FileNameVect ToRm;
294 FileMgr.getFilesNeedToRemove(ToRm);
295
296 ConcatStrings.clear();
297 for (IPOFileMgr::FileNameVect::iterator I = ToRm.begin(), E = ToRm.end();
298 I != E; I++) {
299 StringRef S(*I);
300 ConcatStrings.append(S.begin(), S.end());
301 ConcatStrings.push_back('\0');
302 }
303 ConcatStrings.push_back('\0');
304 ConcatStrings.push_back('\0');
305
306 return ConcatStrings.data();
246307 }
247308
248309 bool LTOCodeGenerator::determineTarget(std::string &errMsg) {
250311 return true;
251312
252313 // if options were requested, set them
253 if (!_codegenOptions.empty())
254 cl::ParseCommandLineOptions(_codegenOptions.size(),
255 const_cast(&_codegenOptions[0]));
314 parseOptions();
256315
257316 std::string TripleStr = _linker.getModule()->getTargetTriple();
258317 if (TripleStr.empty())
383442 _scopeRestrictionsDone = true;
384443 }
385444
445 void LTOCodeGenerator::performIPO(bool ToPartition, std::string &errMsg) {
446 // Mark which symbols can not be internalized
447 applyScopeRestrictions();
448
449 // Instantiate the pass manager to organize the passes.
450 PassManager Passes;
451
452 // Start off with a verification pass.
453 Passes.add(createVerifierPass());
454
455 // Add an appropriate DataLayout instance for this module...
456 Passes.add(new DataLayout(*_target->getDataLayout()));
457 _target->addAnalysisPasses(Passes);
458
459 // Enabling internalize here would use its AllButMain variant. It
460 // keeps only main if it exists and does nothing for libraries. Instead
461 // we create the pass ourselves with the symbol list provided by the linker.
462 if (!DisableOpt)
463 PassManagerBuilder().populateLTOPassManager(Passes,
464 /*Internalize=*/false,
465 !DisableInline,
466 DisableGVNLoadPRE);
467 // Make sure everything is still good.
468 Passes.add(createVerifierPass());
469
470 Module* M = _linker.getModule();
471 if (ToPartition)
472 assert(false && "TBD");
473 else {
474 Passes.run(*M);
475
476 // Create a partition for the merged module.
477 PartitionMgr.createIPOPart(M);
478 }
479 }
480
481 // Perform Post-IPO compilation. If the partition is enabled, there may
482 // be multiple partitions, and therefore there may be multiple objects.
483 // In this case, "MergeObjs" indicates to merge all object together (via ld -r)
484 // and return the path to the merged object via "MergObjPath".
485 //
486 bool LTOCodeGenerator::performPostIPO(std::string &ErrMsg,
487 bool MergeObjs,
488 const char **MergObjPath) {
489 // Determine the variant of post-ipo driver
490 PostIPODriver::VariantTy DrvTy;
491 if (!EnablePartition) {
492 assert(!MergeObjs && !MergObjPath && "Invalid parameter");
493 DrvTy = PostIPODriver::PIDV_SERIAL;
494 } else {
495 DrvTy = PostIPODriver::PIDV_Invalid;
496 assert(false && "TBD");
497 }
498
499 PostIPODriver D(DrvTy, _target, PartitionMgr, FileMgr, MergeObjs);
500 if (D.Compile(ErrMsg)) {
501 if (MergeObjs)
502 *MergObjPath = D.getSingleObjFile()->getPath().c_str();
503 return true;
504 }
505
506 return false;
507 }
508
386509 /// Optimize merged modules using various IPO passes
387510 bool LTOCodeGenerator::generateObjectFile(raw_ostream &out,
388511 std::string &errMsg) {
4040 #include "llvm/Linker.h"
4141 #include
4242 #include
43 #include "LTOPartition.h"
4344
4445 namespace llvm {
4546 class LLVMContext;
101102 //
102103 const void *compile(size_t *length, std::string &errMsg);
103104
105 // Return the paths of the intermediate files that linker needs to delete
106 // before it exits. The paths are delimited by a single '\0', and the last
107 // path is ended by double '\0's. The file could be a directory. In that
108 // case, the entire directory should be erased recusively. This function
109 // must be called after the compilexxx() is successfuly called, because
110 // only after that moment, compiler is aware which files need to be removed.
111 // If calling compilexxx() is not successful, it is up to compiler to clean
112 // up all the intermediate files generated during the compilation process.
113 //
114 const char *getFilesNeedToRemove();
115
104116 private:
105117 void initializeLTOPasses();
118 bool determineTarget(std::string &errMsg);
119 void parseOptions();
120 bool prepareBeforeCompile(std::string &ErrMsg);
106121
122 void performIPO(bool PerformPartition, std::string &ErrMsg);
123 bool performPostIPO(std::string &ErrMsg, bool MergeObjs = false,
124 const char **MergObjPath = 0);
107125 bool generateObjectFile(llvm::raw_ostream &out, std::string &errMsg);
126
108127 void applyScopeRestrictions();
109128 void applyRestriction(llvm::GlobalValue &GV,
110129 std::vector &mustPreserveList,
111130 llvm::SmallPtrSet &asmUsed,
112131 llvm::Mangler &mangler);
113 bool determineTarget(std::string &errMsg);
132
114133
115134 typedef llvm::StringMap StringSet;
116135
126145 std::vector _codegenOptions;
127146 std::string _mCpu;
128147 std::string _nativeObjectPath;
148
149 // To manage the partitions. If partition is not enabled, the whole merged
150 // module is considered as a single degenerated partition, and the "manager"
151 // is still active.
152 lto::IPOPartMgr PartitionMgr;
153
154 // To manage the intermediate files during the compilations.
155 lto::IPOFileMgr FileMgr;
156
157 // Sometimes we need to return a vector of strings in a "C" way (to work with
158 // the C-APIs). We encode such C-thinking string vector by concatenating all
159 // strings tegother with a single '\0' as the delimitor, the last string ended
160 // by double '\0's.
161 SmallVector ConcatStrings;
162
163 // Make sure command line is parsed only once. It would otherwise complain
164 // and quite prematurely.
165 bool OptionsParsed;
129166 };
130167
131168 #endif // LTO_CODE_GENERATOR_H
0 //===-- LTOPartition.cpp - Parition Merged Module --------------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "LTOPartition.h"
10 #include "llvm/ADT/SetVector.h"
11 #include "llvm/ADT/DenseMap.h"
12 #include "llvm/Analysis/CallGraph.h"
13 #include "llvm/Bitcode/ReaderWriter.h"
14 #include "llvm/IR/Module.h"
15 #include "llvm/Support/FileSystem.h"
16 #include "llvm/Support/MemoryBuffer.h"
17 #include "llvm/Support/SourceMgr.h"
18 #include "llvm/Support/raw_ostream.h"
19 #include "llvm/Support/Path.h"
20 #include "llvm/Transforms/Utils/ValueMapper.h"
21 #include "llvm/Transforms/Utils/Cloning.h"
22
23 using namespace llvm;
24 using namespace lto;
25
26 // /////////////////////////////////////////////////////////////////////////////
27 //
28 // Implementation of IPOPartition and IPOPartMgr
29 //
30 // /////////////////////////////////////////////////////////////////////////////
31 //
32 IPOPartition::IPOPartition(Module *M, const char *NameWoExt, IPOFileMgr &FM) :
33 Mod(0), Ctx(0), IRFile(0), ObjFile(0), FileNameWoExt(NameWoExt), FileMgr(FM) {
34 }
35
36 IPOFile &IPOPartition::getIRFile() const {
37 if (IRFile)
38 return *IRFile;
39 else {
40 std::string FN(FileNameWoExt + ".bc");
41 return *(IRFile = FileMgr.createIRFile(FN.c_str()));
42 }
43 }
44
45 IPOFile &IPOPartition::getObjFile() const {
46 if (ObjFile)
47 return *ObjFile;
48 else {
49 std::string FN(FileNameWoExt + ".o");
50 return *(ObjFile = FileMgr.createObjFile(FN.c_str()));
51 }
52 }
53
54 bool IPOPartition::saveBitCode() {
55 if (!Mod) {
56 // The bit-code have already saved in disk.
57 return true;
58 }
59
60 IPOFile &F = getIRFile();
61 if (F.errOccur())
62 return false;
63
64 raw_fd_ostream OF(F.getPath().c_str(), F.getLastErrStr(),
65 sys::fs::F_Binary);
66 WriteBitcodeToFile(Mod, OF);
67 OF.close();
68
69 Mod = 0;
70 delete Ctx;
71 Ctx = 0;
72
73 return !F.errOccur();
74 }
75
76 bool IPOPartition::loadBitCode() {
77 if (Mod)
78 return true;
79
80 IPOFile &F = getIRFile();
81 if (F.errOccur())
82 return false;
83
84 Ctx = new LLVMContext;
85
86 error_code &EC = F.getLastErrCode();
87 std::string &ErrMsg = F.getLastErrStr();
88
89 OwningPtr Buf;
90 if (error_code ec = MemoryBuffer::getFile(F.getPath(), Buf, -1, false)) {
91 EC = ec;
92 ErrMsg += ec.message();
93 return false;
94 }
95
96 Mod = ParseBitcodeFile(Buf.get(), *Ctx, &ErrMsg);
97
98 return Mod != 0;
99 }
100
101 IPOPartition *IPOPartMgr::createIPOPart(Module *M) {
102 std::string PartName;
103 raw_string_ostream OS(PartName);
104 OS << "part" << NextPartId++;
105
106 IPOPartition *P = new IPOPartition(M, OS.str().c_str(), FileMgr);
107 P->Mod = M;
108 IPOParts.push_back(P);
109 return P;
110 }
111
112 // ///////////////////////////////////////////////////////////////////////////
113 //
114 // Implementation of IPOFile and IPOFileMgr
115 //
116 // ///////////////////////////////////////////////////////////////////////////
117 //
118 IPOFile::IPOFile(const char *DirName, const char *BaseName, bool KeepFile)
119 : Fname(BaseName), Keep(KeepFile) {
120 // Concatenate dirname and basename
121 StringRef D(DirName);
122 SmallVector Path(D.begin(), D.end());
123 sys::path::append(Path, Twine(BaseName));
124 Fpath = StringRef(Path.data(), Path.size());
125 }
126
127 IPOFileMgr::IPOFileMgr() {
128 IRFiles.reserve(20);
129 ObjFiles.reserve(20);
130 OtherFiles.reserve(8);
131 KeepWorkDir = false;
132 WorkDirCreated = false;
133 }
134
135 bool IPOFileMgr::createWorkDir(std::string &ErrorInfo) {
136 if (WorkDirCreated)
137 return true;
138
139 error_code EC;
140 if (WorkDir.empty()) {
141 // If the workdir is not specified, then create workdir under current
142 // directory.
143 //
144 SmallString<128> D;
145 if (sys::fs::current_path(D) != error_code::success()) {
146 ErrorInfo += "fail to get current directory";
147 return false;
148 }
149 sys::path::append(D, "llvmipo");
150 sys::fs::make_absolute(D);
151
152 SmallVector ResPath;
153 EC = sys::fs::createUniqueDirectory(Twine(StringRef(D.data(), D.size())),
154 ResPath);
155 WorkDir = StringRef(ResPath.data(), ResPath.size());
156 } else {
157 bool Exist;
158 EC = sys::fs::create_directory(Twine(WorkDir), Exist);
159 }
160
161 if (EC == error_code::success()) {
162 WorkDirCreated = true;
163 return true;
164 }
165
166 return false;
167 }
168
169 IPOFile *IPOFileMgr::createIRFile(const char *Name) {
170 IPOFile *F = CreateFile(Name);
171 IRFiles.push_back(F);
172 return F;
173 }
174
175 IPOFile *IPOFileMgr::createObjFile(const char *Name) {
176 IPOFile *F = CreateFile(Name);
177 ObjFiles.push_back(F);
178 return F;
179 }
180
181 IPOFile *IPOFileMgr::createMakefile(const char *Name) {
182 IPOFile *F = CreateFile(Name);
183 OtherFiles.push_back(F);
184 return F;
185 }
186
187 void IPOFileMgr::removeAllUnneededFiles() {
188 FileNameVect ToRm;
189 getFilesNeedToRemove(ToRm);
190
191 for (SmallVector::iterator I = ToRm.begin(), E = ToRm.end();
192 I != E; I++) {
193 const char *FN = *I;
194 sys::fs::file_status Stat;
195 if (sys::fs::status(Twine(FN), Stat) != error_code::success())
196 continue;
197
198 uint32_t Dummy;
199 if (sys::fs::is_directory(FN))
200 sys::fs::remove_all(Twine(FN), Dummy);
201 else
202 sys::fs::remove(Twine(FN));
203 }
204 }
0 //===-------- LTOPartition.h - Partition related classes and functions ---===//
1 //
2 // This file is distributed under the University of Illinois Open Source
3 // License. See LICENSE.TXT for details.
4 //
5 //===----------------------------------------------------------------------===//
6 //
7 // This file declare the partition related classes and functions. A partition
8 // is a portion of the merged module. In case partition is disabled, the entire
9 // merged module is considered as a degenerated partition.
10 //
11 // The classes declared in this file are:
12 // o. IPOPartition : to depicit a partition
13 // o. IPOFile: It is a "container" collecting miscellaneous information about
14 // an intermeidate file, including file name, path, last-err-message etc.
15 // o. IPOPartMgr, IPOFileMgr: as the name suggests, it's the manager of
16 // IPOPartitions and IPOFiles, respectively.
17 //
18 //===----------------------------------------------------------------------===//
19
20 #ifndef LTO_PARTITION_H
21 #define LTO_PARTITION_H
22
23 #include "llvm/Pass.h"
24 #include "llvm/IR/LLVMContext.h"
25 #include "llvm/Support/system_error.h"
26
27 using namespace llvm;
28
29 namespace lto {
30 /// \brief To collect miscellaneous information about an intermdiate file.
31 ///
32 /// These informration include file name, path, last error message etc.
33 ///
34 class IPOFile {
35 public:
36 const std::string &getName() { return Fname; }
37 const std::string &getPath() { return Fpath; }
38
39 error_code &getLastErrCode() { return LastErr; }
40 std::string &getLastErrStr() { return LastErrStr; }
41
42 bool errOccur() const {
43 return LastErr != error_code::success() || !LastErrStr.empty();
44 }
45
46 // To keep this file after compilation finish.
47 void setKeep() { Keep = true; }
48 bool isKept() const { return Keep; }
49
50 private:
51 friend class IPOFileMgr;
52 IPOFile(const char* DirName, const char *BaseName, bool Keep=false);
53 ~IPOFile();
54
55 private:
56 std::string Fname;
57 std::string Fpath;
58 error_code LastErr;
59 std::string LastErrStr;
60 bool Keep;
61 };
62
63 /// \brief To manage IPOFiles, create and remove work-directory.
64 ///
65 class IPOFileMgr {
66 public:
67 typedef SmallVector FileNameVect;
68
69 IPOFileMgr();
70
71 // NOTE: Do not delete intermeidate in the destructor as we never know
72 // if these files out-last the class or not. It is safe to let linker's
73 // clean-up hook to take care these files.
74 ~IPOFileMgr() {};
75
76 void setWorkDir(const char* WD) {
77 assert(!WorkDirCreated /* Too late to change mind */ &&
78 WorkDir.empty() /* don't change back and forth */ &&
79 "Cannot change work dir");
80 WorkDir = WD;
81 }
82 void setKeepWorkDir(bool Keep) { KeepWorkDir = Keep; }
83 bool IsToKeepWorkDir() const { return KeepWorkDir; }
84 const std::string &getWorkDir() { return WorkDir; }
85
86 bool createWorkDir(std::string &ErrorInfo);
87
88 IPOFile *createIRFile(const char *Name);
89 IPOFile *createObjFile(const char *Name);
90 IPOFile *createMakefile(const char *Name);
91
92 typedef std::vector FileVect;
93 FileVect &getIRFiles() { return IRFiles; }
94 FileVect &getObjFiles() { return ObjFiles; }
95
96 // Get all files/dirs that need to removed after the LTO complete.
97 void getFilesNeedToRemove(FileNameVect &ToRm) {
98 ToRm.clear();
99 if (!IsToKeepWorkDir() && WorkDirCreated)
100 ToRm.push_back(WorkDir.c_str());
101 }
102
103 // Remove all files/dirs returned from getFilesNeedToRemove().
104 void removeAllUnneededFiles();
105
106 private:
107 IPOFile *CreateFile(const char *Name) {
108 return new IPOFile(WorkDir.c_str(), Name);
109 }
110
111 private:
112 FileVect IRFiles;
113 FileVect ObjFiles;
114 FileVect OtherFiles;
115 std::string WorkDir;
116 bool KeepWorkDir;
117 bool WorkDirCreated;
118 };
119
120 /// \brief Describe a partition of the merged module.
121 ///
122 class IPOPartition {
123 public:
124 llvm::Module *getModule() const { return Mod; }
125 IPOFile &getIRFile() const;
126 IPOFile &getObjFile() const;
127 const std::string &getIRFilePath() const { return getIRFile().getPath(); }
128 const std::string &getObjFilePath() const { return getObjFile().getPath(); }
129
130 // If the bitcode reside in memory or disk
131 bool isInMemory() const { return Mod != 0; }
132
133 // Load/store bitcode from/to disk file.
134 bool saveBitCode();
135 bool loadBitCode();
136
137 private:
138 friend class IPOPartMgr;
139 IPOPartition(llvm::Module *M, const char *FileNameWoExt, IPOFileMgr &FM);
140
141 // The module associated with this partition
142 Module *Mod;
143 LLVMContext *Ctx;
144
145 // The bitcode file and its corresponding object file associated with
146 // this partition. The names of these two files are different only in
147 // extension; the "FileNameWoExt" record their (common) name without
148 // extension.
149 //
150 mutable IPOFile *IRFile;
151 mutable IPOFile *ObjFile;
152 std::string FileNameWoExt;
153
154 IPOFileMgr &FileMgr;
155 };
156
157 /// \brief To manage IPOPartitions
158 ///
159 class IPOPartMgr {
160 public:
161 IPOPartMgr(IPOFileMgr &IFM) : FileMgr(IFM), NextPartId(1) {}
162
163 typedef std::vector IPOPartsTy;
164 typedef IPOPartsTy::iterator iterator;
165 typedef IPOPartsTy::const_iterator const_iterator;
166
167 iterator begin() { return IPOParts.begin(); }
168 iterator end() { return IPOParts.end(); }
169 const_iterator begin() const { return IPOParts.begin(); }
170 const_iterator end() const { return IPOParts.end(); }
171
172 IPOPartition *createIPOPart(Module *);
173 IPOPartition *getSinglePartition() {
174 assert(IPOParts.size() == 1 && "Has multiple partition");
175 return IPOParts[0];
176 }
177
178 private:
179 IPOPartsTy IPOParts;
180 IPOFileMgr &FileMgr;
181 int NextPartId;
182 };
183
184 }
185
186 #endif //LTO_PARTITION_H
0 //===---------- LTOPostIPODriver.h - PostIPO Driver -----------------------===//
1 //
2 // This file is distributed under the University of Illinois Open Source
3 // License. See LICENSE.TXT for details.
4 //
5 //===----------------------------------------------------------------------===//
6 //
7 // This file defines the PostIPODriver class which is the driver for Post-IPO
8 // compilation.
9 //
10 //===----------------------------------------------------------------------===//
11
12 #include "llvm/Analysis/AliasAnalysis.h"
13 #include "llvm/IR/DataLayout.h"
14 #include "llvm/PassManager.h"
15 #include "llvm/Support/FileSystem.h"
16 #include "llvm/Support/FormattedStream.h"
17 #include "llvm/Support/Program.h"
18 #include "llvm/Support/raw_ostream.h"
19 #include "llvm/Target/TargetMachine.h"
20 #include "llvm/Transforms/ObjCARC.h"
21 #include "LTOPartition.h"
22 #include "LTOPostIPODriver.h"
23
24 using namespace llvm;
25 using namespace lto;
26
27 // /////////////////////////////////////////////////////////////////////////////
28 //
29 // Declare all variants of Post-IPO drivers
30 //
31 // /////////////////////////////////////////////////////////////////////////////
32 //
33 namespace {
34 /// \breif Base class for all driver variants.
35 ///
36 class PostIPODrvBaseImpl {
37 public:
38 PostIPODrvBaseImpl(TargetMachine *Targ, IPOPartMgr &IPM, IPOFileMgr &IFM,
39 bool ToMergeObjs):
40 PartMgr(IPM), FileMgr(IFM), MergedObjFile(0), Target(Targ),
41 MergeObjs(ToMergeObjs) {}
42
43 virtual ~PostIPODrvBaseImpl() {};
44
45 IPOPartMgr &getPartitionMgr() { return PartMgr; }
46 IPOFileMgr &getFileMgr() { return FileMgr; }
47
48 // Implement the PostIPODriver::getSingleObjFile()
49 virtual IPOFile *getSingleObjFile() const = 0;
50
51 bool IsToMergeObj() const { return MergeObjs; }
52
53 virtual bool Compile(std::string &ErrMsg) = 0;
54
55 protected:
56 // Populate post-IPO scalar optimization pass manager
57 bool PopulatePostIPOOptPM(PassManager &PM);
58
59 // Populate post-IPO machine-specific CodeGen pass manager
60 bool PopulateCodeGenPM(PassManager &PM, formatted_raw_ostream &OutFile,
61 std::string &Err);
62
63 protected:
64 IPOPartMgr &PartMgr;
65 IPOFileMgr &FileMgr;
66 IPOFile *MergedObjFile;
67 TargetMachine *Target;
68 bool MergeObjs;
69 };
70
71 /// \breif PostIPO driver for the compiling the entire program without
72 /// partition.
73 class PostIPODrvSerial : public PostIPODrvBaseImpl {
74 public:
75 PostIPODrvSerial(TargetMachine *T, IPOPartMgr &IPM, IPOFileMgr &IFM,
76 bool ToMergeObjs) :
77 PostIPODrvBaseImpl(T, IPM, IFM, ToMergeObjs) {}
78
79 virtual bool Compile(std::string &ErrMsg);
80 virtual IPOFile *getSingleObjFile() const;
81
82 private:
83 Module *getModule() const { return (*PartMgr.begin())->getModule(); }
84 };
85 }
86
87 // ////////////////////////////////////////////////////////////////////////////
88 //
89 // Implemetation of PostIPODriver
90 //
91 // ////////////////////////////////////////////////////////////////////////////
92 //
93 PostIPODriver::PostIPODriver(VariantTy V, TargetMachine *TM, IPOPartMgr &IPM,
94 IPOFileMgr &IFM, bool ToMergeObjs) {
95 if (V == PIDV_SERIAL)
96 DrvImpl = new PostIPODrvSerial(TM, IPM, IFM, ToMergeObjs);
97 else
98 assert(false && "TBD");
99 }
100
101 bool PostIPODriver::Compile(std::string &ErrMsg) {
102 PostIPODrvBaseImpl *P = static_cast(DrvImpl);
103 return P->Compile(ErrMsg);
104 }
105
106 IPOFile *PostIPODriver::getSingleObjFile() const {
107 PostIPODrvBaseImpl *P = static_cast(DrvImpl);
108 return P->getSingleObjFile();
109 }
110
111 // ////////////////////////////////////////////////////////////////////////////
112 //
113 // Implemetation of PostIPODrvBaseImpl
114 //
115 // ////////////////////////////////////////////////////////////////////////////
116 //
117 bool PostIPODrvBaseImpl::PopulatePostIPOOptPM(PassManager &PM) {
118 (void)PM;
119 return true;
120 }
121
122 bool PostIPODrvBaseImpl::PopulateCodeGenPM(PassManager &PM,
123 formatted_raw_ostream &OutFile,
124 std::string &Err) {
125 PM.add(new DataLayout(*Target->getDataLayout()));
126 Target->addAnalysisPasses(PM);
127
128 // If the bitcode files contain ARC code and were compiled with optimization,
129 // the ObjCARCContractPass must be run, so do it unconditionally here.
130 PM.add(createObjCARCContractPass());
131
132 if (Target->addPassesToEmitFile(PM, OutFile,
133 TargetMachine::CGFT_ObjectFile)) {
134 Err = "target file type not supported";
135 return false;
136 }
137 return true;
138 }
139
140 // ////////////////////////////////////////////////////////////////////////////
141 //
142 // Implemetation of PostIPODrvSerial
143 //
144 // ////////////////////////////////////////////////////////////////////////////
145 //
146 bool PostIPODrvSerial::Compile(std::string &ErrMsg) {
147 Module *M = getModule();
148
149 // Step 1: Run the post-IPO scalar optimizations
150 {
151 PassManager SoptPM;
152 PopulatePostIPOOptPM(SoptPM);
153 SoptPM.run(*M);
154 }
155
156 // Step 2: Run the post-IPO machine-specific code-generation passes
157 {
158 IPOFile &Obj = (*PartMgr.begin())->getObjFile();
159 raw_fd_ostream ros(Obj.getPath().c_str(), Obj.getLastErrStr(),
160 sys::fs::F_Binary);
161 formatted_raw_ostream OutFile(ros);
162
163 PassManager CodGenPM;
164 if (!PopulateCodeGenPM(CodGenPM, OutFile, ErrMsg)) {
165 ErrMsg += Obj.getLastErrStr();
166 return false;
167 }
168
169 CodGenPM.run(*M);
170 }
171
172 return true;
173 }
174
175 IPOFile *PostIPODrvSerial::getSingleObjFile() const {
176 assert(!MergedObjFile && "No need to *merge* a single object file");
177 IPOPartition *P = *PartMgr.begin();
178 return &P->getObjFile();
179 }
0 //===---------- LTOPostIPODriver.h - PostIPO Driver -----------------------===//
1 //
2 // This file is distributed under the University of Illinois Open Source
3 // License. See LICENSE.TXT for details.
4 //
5 //===----------------------------------------------------------------------===//
6 //
7 // This file declare the PostIPODriver class which is the driver for
8 // Post-IPO compilation phase.
9 //
10 //===----------------------------------------------------------------------===//
11
12 #ifndef LTO_POSTIPO_DRIVER_H
13 #define LTO_POSTIPO_DRIVER_H
14
15 #include "llvm/Target/TargetMachine.h"
16
17 namespace lto {
18 class IPOPartMgr;
19 class IPOFileMgr;
20 class IPOFile;
21
22 class PostIPODriver {
23 public:
24 typedef enum {
25 PIDV_Invalid,
26 PIDV_SERIAL, // No partition
27 PIDV_MultiThread, // Each partition is compiled by a thread
28 PIDV_MultiProc, // Each partition is compiled by a process
29 PIDV_MakeUtil // Partitions compilation is driven by a make-utility
30 } VariantTy;
31
32 PostIPODriver(VariantTy Var, TargetMachine *TM, IPOPartMgr &IPM,
33 IPOFileMgr &IFM, bool ToMergeObjs = false);
34
35 // Return the single resulting object file. If there is no prior
36 // compilation failure, this function may return NULL iff:
37 // 1) Partition is enabled, and
38 // 2) Multiple partitions are generated, and
39 // 3) It is not asked to merge together the objects corresponding to the
40 // the partions.
41 IPOFile *getSingleObjFile() const;
42
43 bool Compile(std::string &ErrMsg);
44
45 private:
46 void *DrvImpl;
47 VariantTy DrvStyle;
48 };
49 }
50
51 #endif // LTO_POSTIPO_DRIVER_H
206206 return !cg->compile_to_file(name, sLastErrorString);
207207 }
208208
209 /// Get intermediate files that need to be removed before linker exit. Upon
210 /// return, the paths of the files need to be removed is written to "paths". The
211 /// paths are separated by a single '\0', and the last path is ended by double
212 /// '\0's. A file could be a directory; in this case, the entire directory needs
213 /// to be removed recursively.
214 ///
215 /// It is only necessary to call this function after \p lto_codegen_compile was
216 /// successfully called.
217 void
218 lto_codegen_get_files_need_remove(lto_code_gen_t cg, const char **paths) {
219 *paths = cg->getFilesNeedToRemove();
220 }
221
209222 /// lto_codegen_debug_options - Used to pass extra options to the code
210223 /// generator.
211224 void lto_codegen_debug_options(lto_code_gen_t cg, const char *opt) {
1919 lto_codegen_compile
2020 lto_codegen_create
2121 lto_codegen_dispose
22 lto_codegen_get_files_need_remove
2223 lto_codegen_set_debug_model
2324 lto_codegen_set_pic_model
2425 lto_codegen_write_merged_modules